Files
youtube-app/backend/stream/stream_service.py
Marek Lenczewski 8f15f51bce update
2026-04-07 16:13:16 +02:00

92 lines
2.3 KiB
Python

import subprocess
from pathlib import Path
VIDEOS_DIR = "/videos"
CHUNK_SIZE = 64 * 1024
def _get_stream_urls(youtube_url: str):
result = subprocess.run(
[
"yt-dlp",
"-f", "bestvideo[ext=mp4][vcodec^=avc]+bestaudio[ext=m4a]/best[ext=mp4]",
"--print", "urls",
youtube_url,
],
capture_output=True, text=True, timeout=30,
)
if result.returncode != 0:
return None, None
lines = result.stdout.strip().splitlines()
if len(lines) >= 2:
return lines[0], lines[1]
elif len(lines) == 1:
return lines[0], None
return None, None
def stream_video_live(video_id: int, youtube_url: str):
output_path = f"{VIDEOS_DIR}/{video_id}.mp4"
video_url, audio_url = _get_stream_urls(youtube_url)
if not video_url:
return
if audio_url:
cmd = [
"ffmpeg",
"-reconnect", "1",
"-reconnect_streamed", "1",
"-reconnect_delay_max", "5",
"-i", video_url,
"-reconnect", "1",
"-reconnect_streamed", "1",
"-reconnect_delay_max", "5",
"-i", audio_url,
"-c:v", "copy",
"-c:a", "aac",
"-movflags", "frag_keyframe+empty_moov+default_base_moof",
"-f", "mp4",
"pipe:1",
]
else:
cmd = [
"ffmpeg",
"-reconnect", "1",
"-reconnect_streamed", "1",
"-reconnect_delay_max", "5",
"-i", video_url,
"-c", "copy",
"-movflags", "frag_keyframe+empty_moov+default_base_moof",
"-f", "mp4",
"pipe:1",
]
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
)
try:
with open(output_path, "wb") as f:
while True:
chunk = process.stdout.read(CHUNK_SIZE)
if not chunk:
break
f.write(chunk)
yield chunk
except GeneratorExit:
pass
finally:
if process.poll() is None:
process.kill()
process.wait()
if process.stdout:
process.stdout.close()
path = Path(output_path)
if process.returncode != 0 and path.exists():
path.unlink()