This commit is contained in:
Marek
2026-04-05 23:26:55 +02:00
parent b3b4410ee0
commit b6635a107d
21 changed files with 229 additions and 75 deletions

View File

@@ -12,7 +12,7 @@ def download_video(video_id: int, youtube_url: str):
subprocess.run(
[
"yt-dlp",
"-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]",
"-f", "bestvideo[ext=mp4][vcodec^=avc]+bestaudio[ext=m4a]/best[ext=mp4]",
"-o", output_path,
"--merge-output-format", "mp4",
youtube_url,

View File

@@ -1,32 +1,53 @@
import subprocess
import time
from pathlib import Path
VIDEOS_DIR = "/videos"
def stream_video_live(youtube_url: str):
result = subprocess.run(
def stream_video_live(video_id: int, youtube_url: str):
output_path = f"{VIDEOS_DIR}/{video_id}.mp4"
path = Path(output_path)
process = subprocess.Popen(
[
"yt-dlp",
"-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best",
"-g", youtube_url,
"-f", "best[ext=mp4][vcodec^=avc]/best[ext=mp4]",
"-o", output_path,
youtube_url,
],
capture_output=True, text=True, check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
urls = result.stdout.strip().split("\n")
cmd = ["ffmpeg"]
for url in urls:
cmd.extend(["-i", url])
cmd.extend(["-c", "copy", "-movflags", "frag_keyframe+empty_moov", "-f", "mp4", "pipe:1"])
# Warte bis Datei existiert und mindestens 1MB hat
while process.poll() is None:
if path.exists() and path.stat().st_size >= 1024 * 1024:
break
time.sleep(0.5)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
try:
while True:
chunk = process.stdout.read(1024 * 1024)
if not chunk:
break
yield chunk
if not path.exists():
process.wait()
except GeneratorExit:
process.kill()
finally:
if process.poll() is None:
process.kill()
return
# Streame aus der wachsenden Datei
pos = 0
stall_count = 0
with open(output_path, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if chunk:
pos += len(chunk)
stall_count = 0
yield chunk
else:
if process.poll() is not None:
# Download fertig — restliche Bytes lesen
remaining = f.read()
if remaining:
yield remaining
break
stall_count += 1
if stall_count > 60: # 30 Sekunden ohne neue Daten
break
time.sleep(0.5)

View File

@@ -48,16 +48,20 @@ def update_file_path(db: Session, video_id: int, path: str):
db.commit()
def delete_not_downloaded(db: Session, profile_id: int) -> int:
videos = db.query(Video).filter(
Video.file_path.is_(None),
def delete_not_downloaded(db: Session, profile_id: int, exclude_ids: list[int] | None = None) -> int:
query = db.query(Video).filter(
Video.profiles.any(Profile.id == profile_id),
).all()
count = len(videos)
for video in videos:
db.delete(video)
)
if exclude_ids:
query = query.filter(Video.id.notin_(exclude_ids))
videos = query.all()
video_ids = [v.id for v in videos]
if not video_ids:
return 0
db.execute(video_profiles.delete().where(video_profiles.c.video_id.in_(video_ids)))
db.query(Video).filter(Video.id.in_(video_ids)).delete(synchronize_session=False)
db.commit()
return count
return len(video_ids)
def get_all_profiles(db: Session) -> list[Profile]: