71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
import subprocess
|
|
import os
|
|
from config import settings
|
|
|
|
|
|
class TranscodeManager:
|
|
_processes: dict[str, list[subprocess.Popen]] = {}
|
|
|
|
def start_transcode(self, stream_key: str, input_url: str, profile: str = "standard"):
|
|
if stream_key in self._processes:
|
|
return
|
|
|
|
procs = []
|
|
qualities = settings.transcode_profiles.get(profile, settings.qualities)
|
|
segment_seconds = max(1, settings.hls_segment_seconds)
|
|
keyframe_frames = segment_seconds * 30
|
|
for quality in qualities:
|
|
label = quality["label"]
|
|
width = quality["width"]
|
|
height = quality["height"]
|
|
bitrate = quality["bitrate"]
|
|
hls_dir = f"/tmp/hls/{stream_key}/{label}"
|
|
os.makedirs(hls_dir, exist_ok=True)
|
|
cmd = [
|
|
"ffmpeg", "-y",
|
|
"-i", input_url,
|
|
"-c:v", "libx264", "-preset", "ultrafast",
|
|
"-b:v", bitrate,
|
|
"-s", f"{width}x{height}",
|
|
"-sc_threshold", "0",
|
|
"-g", str(keyframe_frames),
|
|
"-keyint_min", str(keyframe_frames),
|
|
"-force_key_frames", f"expr:gte(t,n_forced*{segment_seconds})",
|
|
"-copyts", "-start_at_zero",
|
|
"-c:a", "aac", "-b:a", "128k",
|
|
"-f", "hls",
|
|
"-hls_time", str(segment_seconds),
|
|
"-hls_list_size", "6",
|
|
"-hls_flags", "delete_segments+independent_segments+program_date_time",
|
|
"-hls_segment_filename", f"{hls_dir}/segment_%03d.ts",
|
|
f"{hls_dir}/index.m3u8",
|
|
]
|
|
try:
|
|
proc = subprocess.Popen(
|
|
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
|
)
|
|
procs.append(proc)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
self._processes[stream_key] = procs
|
|
|
|
def stop_transcode(self, stream_key: str):
|
|
procs = self._processes.pop(stream_key, [])
|
|
for proc in procs:
|
|
try:
|
|
proc.terminate()
|
|
proc.wait(timeout=5)
|
|
except Exception:
|
|
try:
|
|
proc.kill()
|
|
except Exception:
|
|
pass
|
|
|
|
def stop_all(self):
|
|
for key in list(self._processes.keys()):
|
|
self.stop_transcode(key)
|
|
|
|
|
|
transcode_mgr = TranscodeManager()
|