Skip to content

Instantly share code, notes, and snippets.

@golyalpha
Last active September 20, 2023 11:24
Show Gist options
  • Save golyalpha/f21c1e37fa0216aa463f878e65637a36 to your computer and use it in GitHub Desktop.
Save golyalpha/f21c1e37fa0216aa463f878e65637a36 to your computer and use it in GitHub Desktop.
My experiments with HLS and FFMPEG
from logging import getLogger, basicConfig, INFO, DEBUG
from os import path, makedirs, chdir
from json import loads
from ffmpeg import Progress
from ffmpeg.asyncio import FFmpeg
from tqdm import tqdm
basicConfig(level=INFO)
logger = getLogger(__name__)
async def hls_stream_multiple(inputs, output):
if not path.exists(output):
makedirs(output)
chdir(output)
for source in inputs:
logger.info("Starting packaging process for %s", source)
ffprobe = (
FFmpeg("ffprobe")
.option("hide_banner")
.option("show_format")
.option("show_streams")
.option("of", "json")
.option("count_packets")
.input(source)
)
mediainfo = loads(await ffprobe.execute())
videostream = None
for stream in mediainfo["streams"]:
if stream["codec_type"] == "video":
videostream = stream
break
if videostream is None:
raise RuntimeError("No video stream found in source")
progressbar = tqdm(
desc=f"Packaging {path.split(source)[1]}...",
unit="f",
total=int(stream["nb_read_packets"])
)
ffmpeg = (
FFmpeg()
.option("hide_banner")
.option("y")
.option("re")
.input(source)
.output(
R"playout.m3u8",
{
"c:v": "h264",
"b:v": "10M",
"profile:v": "High",
"level": "4.2",
"r": "60",
"x264-params": "keyint=60:min-keyint=30:scenecut=-1",
"tune": "zerolatency",
"c:a": "aac",
"b:a": "192k",
"f": "hls",
"hls_time": "10",
"hls_flags": "append_list+delete_segments+omit_endlist+discont_start",
"hls_segment_filename": "playout-%04d.ts"
}
)
)
@ffmpeg.on("start")
def _log_arguments(args):
logger.debug(" ".join(args))
@ffmpeg.on("stderr")
def _log_stderr(line):
_logger = logger.getChild("ffmpeg")
_logger.debug(line)
@ffmpeg.on("progress")
def _progress_update(progress:Progress):
progressbar.update(progress.frame - progressbar.n)
_logger = logger.getChild("ffmpeg")
_logger.debug(progress)
@ffmpeg.on("terminated")
@ffmpeg.on("completed")
def _complete():
progressbar.close()
try:
await ffmpeg.execute()
finally:
try:
ffmpeg.terminate()
except:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment