Files
youtube-app/backend/stream/stream_service.py
Marek Lenczewski ca988345e9 update
2026-04-07 17:55:30 +02:00

92 lines
2.3 KiB
Python

import subprocess
from pathlib import Path
VIDEOS_DIR = "/videos"
CHUNK_SIZE = 64 * 1024
def _getStreamUrls(youtubeUrl: str):
result = subprocess.run(
[
"yt-dlp",
"-f", "bestvideo[ext=mp4][vcodec^=avc]+bestaudio[ext=m4a]/best[ext=mp4]",
"--print", "urls",
youtubeUrl,
],
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 streamVideoLive(videoId: int, youtubeUrl: str):
outputPath = f"{VIDEOS_DIR}/{videoId}.mp4"
videoUrl, audioUrl = _getStreamUrls(youtubeUrl)
if not videoUrl:
return
if audioUrl:
cmd = [
"ffmpeg",
"-reconnect", "1",
"-reconnect_streamed", "1",
"-reconnect_delay_max", "5",
"-i", videoUrl,
"-reconnect", "1",
"-reconnect_streamed", "1",
"-reconnect_delay_max", "5",
"-i", audioUrl,
"-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", videoUrl,
"-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(outputPath, "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(outputPath)
if process.returncode != 0 and path.exists():
path.unlink()