From 28f9defc9b2b5086660cec5f94d4a8de8d6cf06a Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Mon, 12 Jan 2026 20:19:56 -0500 Subject: [PATCH] Add support for streaming single local video files --- README.md | 31 +++++++++++++++++++++- stream_m3u_to_rtmp.py | 60 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6f6b881..c8dcbbc 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,11 @@ Python script to stream M3U playlist files to RTMP servers using ffmpeg without ### Basic Usage ```bash +# Stream M3U playlist python stream_m3u_to_rtmp.py + +# Stream single video file +python stream_m3u_to_rtmp.py --single-file ``` ### Examples @@ -41,6 +45,22 @@ python stream_m3u_to_rtmp.py \ "playlist.m3u" \ "rtmp://live.twitch.tv/app/your_stream_key" +# Stream single local video file +python stream_m3u_to_rtmp.py \ + "video.mp4" \ + "rtmp://server.com/live/stream_key" \ + --single-file + +# Stream single video file (auto-detected by extension) +python stream_m3u_to_rtmp.py \ + "video.mp4" \ + "rtmp://server.com/live/stream_key" + +# Stream single video URL +python stream_m3u_to_rtmp.py \ + "https://example.com/video.mp4" \ + "rtmp://server.com/live/stream_key" + # Stream with absolute path python stream_m3u_to_rtmp.py \ "C:/path/to/playlist.m3u" \ @@ -95,10 +115,19 @@ Examples: ## Options -- `--loop-playlist`: Loop through the entire playlist when finished +- `--loop-playlist`: Loop through the entire playlist when finished (M3U only) - `--loop-video`: Loop each individual video file indefinitely +- `--single-file`: Treat input as a single video file instead of M3U playlist - `--ffmpeg`: Specify custom path to ffmpeg executable +## Input Types + +The script supports two input types: + +1. **M3U Playlist Files**: Automatically detected by file extension (.m3u, .m3u8) +2. **Single Video Files**: Automatically detected by video extensions (.mp4, .mkv, .avi, etc.) or use `--single-file` flag +3. **Video URLs**: HTTP/HTTPS URLs are automatically treated as single video files + ## How It Works The script: diff --git a/stream_m3u_to_rtmp.py b/stream_m3u_to_rtmp.py index 72dd4e9..25f8eca 100644 --- a/stream_m3u_to_rtmp.py +++ b/stream_m3u_to_rtmp.py @@ -214,11 +214,11 @@ def stream_m3u_to_rtmp(m3u_path, rtmp_url, ffmpeg_path='ffmpeg', loop_playlist=F def main(): parser = argparse.ArgumentParser( - description='Stream M3U playlist files to RTMP server without re-encoding' + description='Stream M3U playlist files or single video files to RTMP server without re-encoding' ) parser.add_argument( - 'm3u_file', - help='Path to M3U playlist file' + 'input', + help='Path to M3U playlist file or single video file' ) parser.add_argument( 'rtmp_url', @@ -232,23 +232,61 @@ def main(): parser.add_argument( '--loop-playlist', action='store_true', - help='Loop through the entire playlist when finished' + help='Loop through the entire playlist when finished (M3U only)' ) parser.add_argument( '--loop-video', action='store_true', help='Loop each individual video file' ) + parser.add_argument( + '--single-file', + action='store_true', + help='Treat input as a single video file instead of M3U playlist' + ) args = parser.parse_args() - success = stream_m3u_to_rtmp( - args.m3u_file, - args.rtmp_url, - args.ffmpeg, - args.loop_playlist, - args.loop_video - ) + # Check if input is a single video file + input_path = os.path.abspath(args.input) + is_single_file = args.single_file + + # Auto-detect if not explicitly set + if not is_single_file: + # Check if file exists and has video extension + video_extensions = ['.mp4', '.mkv', '.avi', '.mov', '.flv', '.wmv', '.webm', '.m4v', '.ts', '.m2ts'] + if os.path.exists(input_path): + _, ext = os.path.splitext(input_path.lower()) + if ext in video_extensions: + is_single_file = True + # If it's a URL, treat as single file + elif args.input.startswith('http://') or args.input.startswith('https://'): + is_single_file = True + + if is_single_file: + # Stream single video file + print(f"Streaming single video file: {args.input}") + print(f"Streaming to: {args.rtmp_url}") + print("Press Ctrl+C to stop streaming...\n") + + is_url = args.input.startswith('http://') or args.input.startswith('https://') + success = stream_video_to_rtmp( + args.input, + args.rtmp_url, + args.ffmpeg, + args.loop_video, + is_url + ) + else: + # Stream M3U playlist + success = stream_m3u_to_rtmp( + args.input, + args.rtmp_url, + args.ffmpeg, + args.loop_playlist, + args.loop_video + ) + sys.exit(0 if success else 1) if __name__ == '__main__':