Last active
September 29, 2023 17:47
-
-
Save rakeshopensource/1a21a0368e952353fd3b5b3f30344e4e to your computer and use it in GitHub Desktop.
This handles video streaming and transcoding using FFmpeg. It listens for incoming video streams, transcodes them into different resolutions (720p and 1080p), and generates an HLS (HTTP Live Streaming) playlist file (master.m3u8) that references the transcoded video segments.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import subprocess | |
import threading | |
from fastapi import FastAPI | |
from starlette.responses import Response | |
from threading import Lock | |
app = FastAPI() | |
lock = Lock() | |
# Function to append content to the master.m3u8 playlist | |
def append_to_master_m3u8(content): | |
with lock: | |
if not os.path.exists("master.m3u8"): | |
with open("master.m3u8", "w") as f: | |
f.write("#EXTM3U\n") | |
f.write("#EXT-X-VERSION:3\n") | |
f.write("#EXT-X-TARGETDURATION:1\n") | |
f.write("#EXT-X-MEDIA-SEQUENCE:0\n") | |
f.write("#EXT-X-PLAYLIST-TYPE:VOD\n") | |
f.write("#EXT-X-ALLOW-CACHE:NO\n") | |
with open("master.m3u8", "a") as f: | |
f.write(content) | |
# Function to transcode the video stream | |
def transcode(stream_name, resolution, bitrate, scale): | |
cmd = [ | |
"ffmpeg", "-i", f"rtmp://localhost/live/{stream_name}", "-vf", f"scale=-1:{scale},format=yuv422p", | |
"-c:v", "libx264", "-b:v", f"{bitrate}k", "-c:a", "aac", "-f", "hls", "-hls_time", "1", | |
f"-hls_segment_filename", f"{resolution}/output_%03d.ts", f"{resolution}/{resolution}.m3u8" | |
] | |
subprocess.run(cmd) | |
append_to_master_m3u8(f"#EXT-X-STREAM-INF:BANDWIDTH={bitrate}000,RESOLUTION={scale}\n{resolution}/{resolution}.m3u8\n") | |
# HTTP POST endpoint to handle incoming video streams | |
@app.post("/on_publish") | |
def on_publish(name: str): | |
stream_name = name | |
# Create directories and set permissions | |
for dir_name in ["720p", "1080p"]: | |
os.makedirs(dir_name, exist_ok=True) | |
os.chmod(dir_name, 0o755) | |
# Transcode in parallel for 720p and 1080p | |
threading.Thread(target=transcode, args=(stream_name, "720p", "2000", "720")).start() | |
threading.Thread(target=transcode, args=(stream_name, "1080p", "3000", "1080")).start() | |
return Response(content="OK", status_code=200) | |
if __name__ == "__main__": | |
import uvicorn | |
uvicorn.run(app, host="0.0.0.0", port=8080) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment