├── README.md ├── run_live_vp9_ffmpeg_chk_generation.sh ├── run_live_vp9_ffmpeg_dash_mpd_generation.sh ├── short_bbb.mp4 ├── start_dash_abr_live_stream.sh ├── start_hls_abr_live_stream.sh ├── start_hls_abr_live_stream_file_loop.sh ├── start_hls_low_latency_live_stream.sh ├── start_http_server.sh └── start_mpeg_dash_low_latency_live_stream.sh /README.md: -------------------------------------------------------------------------------- 1 | # Live stream from your desktop 2 | It provides guidance to test live streaming (mostly RTMP, SRT, mpeg-dash or hls) or vod from your own desktop using [FFmpeg](https://ffmpeg.org/), it's pretty useful for testing and learning purposes. 3 | 4 | ## MacOS 5 | 6 | > #### Tested with: 7 | > * MacOS High Siera 10.13, 10.15.2, Ubuntu 18.04 8 | > * **Warning:** The video asset used for looping streaming is more than hundreds of MBs. 9 | 10 | ### Requirements 11 | 12 | ```bash 13 | docker 14 | wget 15 | curl 16 | ``` 17 | ### Simulating HLS / DASH with multiple renditions/resolutions and DVR 18 | 19 | #### HLS 20 | 21 | Run this server in one of your tabs: 22 | ```bash 23 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_http_server.sh | sh 24 | ``` 25 | Run this encoder in another of your tabs: 26 | ```bash 27 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_hls_abr_live_stream.sh | sh 28 | ``` 29 | Access the stream at http://localhost:8080/master.m3u8 or at [clappr's demo page](http://clappr.io/demo/#dmFyIHBsYXllckVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicGxheWVyLXdyYXBwZXIiKTsKCnZhciBwbGF5ZXIgPSBuZXcgQ2xhcHByLlBsYXllcih7CiAgc291cmNlOiAnaHR0cDovL2xvY2FsaG9zdDo4MDgwL21hc3Rlci5tM3U4JywKICBwb3N0ZXI6ICdodHRwOi8vY2xhcHByLmlvL3Bvc3Rlci5wbmcnLAogIG11dGU6IHRydWUsCiAgaGVpZ2h0OiAzNjAsCiAgd2lkdGg6IDY0MAp9KTsKCnBsYXllci5hdHRhY2hUbyhwbGF5ZXJFbGVtZW50KTsK) 30 | 31 | ##### HLS looping the file 32 | 33 | **If you want to use a video file instead of a synthetic media**, run this encoder in another of your tabs: 34 | ```bash 35 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_hls_abr_live_stream_file_loop.sh | sh 36 | ``` 37 | 38 | #### DASH 39 | 40 | Run this server in one of your tabs: 41 | ```bash 42 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_http_server.sh | sh 43 | ``` 44 | Run this encoder in another of your tabs: 45 | ```bash 46 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_dash_abr_live_stream.sh | sh 47 | ``` 48 | Access the stream at http://localhost:8080/out.mpd or go to [dashjs's demo page](http://reference.dashif.org/dash.js/v2.3.0/samples/dash-if-reference-player/index.html?mpd=http://localhost:8080/out.mpd) 49 | 50 | ### Simulating an HLS and MPEG-DASH live streaming for latency comparison 51 | 52 | #### HLS 53 | 54 | Run this server in one of your tabs: 55 | ```bash 56 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_http_server.sh | sh 57 | ``` 58 | Run this encoder in another of your tabs: 59 | ```bash 60 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_hls_low_latency_live_stream.sh | sh 61 | ``` 62 | Access the stream at http://localhost:8080/stream.m3u8 or at [clappr's demo page](http://clappr.io/demo/#dmFyIHBsYXllckVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicGxheWVyLXdyYXBwZXIiKTsKCnZhciBwbGF5ZXIgPSBuZXcgQ2xhcHByLlBsYXllcih7CiAgc291cmNlOiAnaHR0cDovL2xvY2FsaG9zdDo4MDgwL3N0cmVhbS5tM3U4JywKICBwb3N0ZXI6ICdodHRwOi8vY2xhcHByLmlvL3Bvc3Rlci5wbmcnLAogIGhsc2pzQ29uZmlnOiB7bGl2ZVN5bmNEdXJhdGlvbkNvdW50OiAyfSwKICBhdXRvUGxheTogdHJ1ZSwKICBtdXRlOiB0cnVlLAogIGhlaWdodDogMzYwLAogIHdpZHRoOiA2NDAKfSk7CgpwbGF5ZXIuYXR0YWNoVG8ocGxheWVyRWxlbWVudCk7Cgp2YXIgcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAiKTsKcC5zdHlsZS5jc3NUZXh0ID0gInotaW5kZXg6IDk5OTk5OTsgcG9zaXRpb246YWJzb2x1dGU7IHJpZ2h0OjA7IHRvcDowOyBmb250LXNpemU6IDM0cHg7IGNvbG9yOiBibGFjazsgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IiA7CmRvY3VtZW50LmJvZHkucHJlcGVuZChwKTsKbXlJbnRlcnZhbElEID0gc2V0SW50ZXJ2YWwoKCk9PiBwLmlubmVyVGV4dCA9IG5ldyBEYXRlKCkudG9Mb2NhbGVTdHJpbmcoKSwgMTAwMCk7) 63 | 64 | 65 | #### MPEG-DASH 66 | 67 | Run this server in one of your tabs: 68 | ```bash 69 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_http_server.sh | sh 70 | ``` 71 | Run this encoder in another of your tabs: 72 | ```bash 73 | curl -s https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/master/start_mpeg_dash_low_latency_live_stream.sh | sh 74 | ``` 75 | Access the stream at http://localhost:8080/stream.mpd 76 | 77 | ### Requirements 78 | 79 | ```bash 80 | # I assume you have brew already 81 | 82 | # or you could use curl 83 | brew install wget 84 | brew install ffmpeg 85 | brew install node 86 | 87 | # the http server 88 | npm install http-server -g 89 | 90 | # WARNING IT IS A HUGE download file (263M) 91 | wget -O bunny_1080p_30fps.mp4 http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4 92 | 93 | ``` 94 | 95 | ### Sending live RTMP from your local machine 96 | 97 | #### Single Bitrate 98 | 99 | From a pseudo FFmpeg video source color bar and generated audio signal made of a sine wave with amplitude 1/8. 100 | 101 | ``` 102 | ffmpeg -hide_banner \ 103 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 104 | -f lavfi -i "sine=frequency=1000:sample_rate=4800" \ 105 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 106 | -b:v 1400k -bufsize 2800k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 107 | -c:a aac -b:a 128k -f flv rtmp://:1935/live/ 108 | ``` 109 | 110 | From a file. 111 | 112 | ``` 113 | ffmpeg -stream_loop -1 \ 114 | -re -i .mp4 -c:v libx264 \ 115 | -x264opts keyint=30:min-keyint=30:scenecut=-1 -tune zerolatency \ 116 | -s 1280x720 -b:v 1400k -bufsize 2800k \ 117 | -f flv rtmp://:1935/live/ 118 | ``` 119 | 120 | #### Multiple Bitrates 121 | 122 | From a pseudo FFmpeg video source color bar and generated audio signal made of a sine wave with amplitude 1/8. 123 | 124 | ``` 125 | ffmpeg -hide_banner \ 126 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 127 | -f lavfi -i "sine=frequency=1000:sample_rate=4800" \ 128 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 129 | -b:v 1400k -bufsize 2800k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 130 | -c:a aac -b:a 128k -f flv rtmp://:1935/live/ \ 131 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 132 | -b:v 750k -bufsize 1500k -s 640x360 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 133 | -c:a aac -b:a 128k -f flv rtmp://:1935/live/ 134 | ``` 135 | 136 | From a file. 137 | 138 | ``` 139 | ffmpeg -stream_loop -1 \ 140 | -re -i .mp4 -c:v libx264 \ 141 | -x264opts keyint=30:min-keyint=30:scenecut=-1 -tune zerolatency \ 142 | -s 1280x720 -b:v 1400k -bufsize 2800k \ 143 | -f flv rtmp://:1935/live/ \ 144 | -x264opts keyint=30:min-keyint=30:scenecut=-1 -tune zerolatency \ 145 | -s 640x360 -b:v 750k -bufsize 1500k \ 146 | -f flv rtmp://:1935/live/ 147 | ``` 148 | 149 | ### Simulating a MPEG-DASH live streaming from a file 150 | 151 | Open a terminal and run the ffmpeg command: 152 | 153 | ``` 154 | ffmpeg -stream_loop -1 -re -i bunny_1080p_30fps.mp4 \ 155 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 156 | -preset superfast -profile:v baseline -level 3.0 \ 157 | -tune zerolatency -s 1280x720 -b:v 1400k \ 158 | -bufsize 1400k -use_timeline 1 -use_template 1 \ 159 | -init_seg_name init-\$RepresentationID\$.mp4 \ 160 | -min_seg_duration 2000000 -media_seg_name test-\$RepresentationID\$-\$Number\$.mp4 \ 161 | -f dash stream.mpd 162 | ``` 163 | 164 | In another tab, run the following command to fire up the server: 165 | 166 | ``` 167 | http-server -a :: -p 8081 --cors -c-1 168 | ``` 169 | 170 | Now you can test this with your player (using the URL `http://localhost:8081/stream.mpd`). 171 | 172 | ### Simulating an HLS live streaming from a file 173 | 174 | Open a terminal and run the ffmpeg command: 175 | 176 | ``` 177 | ffmpeg -stream_loop -1 -re -i bunny_1080p_30fps.mp4 -c:v libx264 \ 178 | -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 179 | -tune zerolatency -s 1280x720 \ 180 | -b:v 1400k -bufsize 1400k \ 181 | -hls_start_number_source epoch -f hls stream.m3u8 182 | ``` 183 | 184 | In another tab, run the following command to fire up the server: 185 | 186 | ``` 187 | http-server -a :: -p 8081 --cors -c-1 188 | ``` 189 | 190 | Now you can test this with your player (using the URL `http://localhost:8081/stream.m3u8`). 191 | 192 | ### Simulating a MPEG-DASH live streaming from MacOS camera 193 | 194 | Open a terminal and run the ffmpeg command: 195 | 196 | ``` 197 | ffmpeg -re -pix_fmt uyvy422 -f avfoundation -i "0" -pix_fmt yuv420p \ 198 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 199 | -preset superfast -profile:v baseline -level 3.0 \ 200 | -tune zerolatency -s 1280x720 -b:v 1400k \ 201 | -bufsize 1400k -use_timeline 1 -use_template 1 \ 202 | -init_seg_name init-\$RepresentationID\$.mp4 \ 203 | -min_seg_duration 2000000 -media_seg_name test-\$RepresentationID\$-\$Number\$.mp4 \ 204 | -f dash stream.mpd 205 | ``` 206 | 207 | In another tab, run the following command to fire up the server: 208 | 209 | ``` 210 | http-server -a :: -p 8081 --cors -c-1 211 | ``` 212 | 213 | Now you can test this with your player (using the URL `http://localhost:8081/stream.mpd`). 214 | 215 | ### Simulating a HLS live streaming from MacOS camera 216 | 217 | 218 | #### Playing Camera/Mic in FFplay 219 | 220 | ``` 221 | ffplay -f avfoundation -video_device_index 0 -audio_device_index 0 \ 222 | -pixel_format uyvy422 -framerate 30 -video_size 1280x720 -i "default" 223 | ``` 224 | 225 | #### MacOS Camera/Mic to HLS 226 | 227 | Open a terminal and run the ffmpeg command: 228 | 229 | ``` 230 | ffmpeg -f avfoundation -video_device_index 0 -audio_device_index 0 \ 231 | -pixel_format uyvy422 -framerate 30 -video_size 640x480 -i "default" \ 232 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 233 | -tune zerolatency -b:v 1000k -bufsize 2000k \ 234 | -c:a aac -b:a 128k \ 235 | -hls_time 5 -hls_start_number_source epoch \ 236 | -f hls stream.m3u8 237 | ``` 238 | 239 | In another tab, run the following command to fire up the server: 240 | 241 | ``` 242 | http-server -a :: -p 8081 --cors -c-1 243 | ``` 244 | 245 | Now you can test this with your player (using the URL `http://localhost:8081/stream.m3u8`). 246 | 247 | 248 | ### MacOS Camera/Mic to Twitch/Youtube/RTMP 249 | 250 | Open a terminal and run the ffmpeg command: 251 | 252 | ``` 253 | ffmpeg -f avfoundation -video_device_index 0 -audio_device_index 0 \ 254 | -pixel_format uyvy422 -framerate 30 -video_size 640x480 -i "default" \ 255 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 256 | -tune zerolatency -b:v 600k -bufsize 1200k -preset superfast \ 257 | -c:a aac -b:a 128k \ 258 | -f flv rtmp://yourserver:1935/live/yourstream_key 259 | ``` 260 | 261 | ### Simulating an RTMP live streaming listening server with FFmpeg 262 | 263 | ```bash 264 | #!/bin/bash 265 | # this is necessary since ffmpeg stop listening once a player drops 266 | while true 267 | do 268 | ffmpeg -hide_banner -loglevel verbose \ 269 | -re -f lavfi -i testsrc2=size=1280x720:rate=30,format=yuv420p \ 270 | -f lavfi -i sine=frequency=1000:sample_rate=44100 \ 271 | -c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline \ 272 | -vf "drawtext=text='RTMP streaming':box=1:boxborderw=10:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=128:fontcolor=black" \ 273 | -b:v 1000k -bufsize 2000k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 274 | -c:a aac -b:a 128k \ 275 | -f flv -listen 1 -rtmp_live live "rtmp://0.0.0.0:1935/live/app" 276 | sleep 0.4 277 | done 278 | 279 | ``` 280 | 281 | ### Simulating an SRT live streaming 282 | 283 | ```bash 284 | ffmpeg -hide_banner -loglevel verbose \ 285 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 286 | -f lavfi -i "sine=frequency=1000:sample_rate=44100" \ 287 | -c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline \ 288 | -b:v 1000k -bufsize 2000k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 289 | -f mpegts "srt://0.0.0.0:1234?mode=listener&smoother=live&transtype=live" 290 | ``` 291 | 292 | # Bonus Round: 293 | 294 | ## FFmpeg generating sample files for testing purpose 295 | 296 | You can replace codecs, duration, text, and parameters (resolution, sample rate, presets, and so on) to attend your needs. Here's 10.5 seconds clip. 297 | 298 | ```bash 299 | ffmpeg -y -hide_banner -loglevel verbose \ 300 | -f lavfi -i 'testsrc2=size=768x432:duration=10.5:rate=30,format=yuv420p' \ 301 | -f lavfi -i 'sine=frequency=1000:duration=10.5:sample_rate=44100' \ 302 | -c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline \ 303 | -vf "drawtext=text='Sample Test H264/AAC':box=1:boxborderw=10:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=64:fontcolor=black" \ 304 | -b:v 1000k -bufsize 1000k -x264opts 'keyint=30:min-keyint=30:scenecut=-1' \ 305 | -c:a aac -b:a 128k \ 306 | sample_10.5s_h246_30fps_768x432_aac_44100.mp4 307 | ``` 308 | 309 | ## FFmpeg generating noise from /dev/random 310 | 311 | It generates video and audio from [/dev/urandom](https://en.wikipedia.org/wiki//dev/random) device, it produces a stream that looks A LOT like [an old analog TV noise](https://en.wikipedia.org/wiki/Noise_(video)). 312 | 313 | > In analog video and television, is a random dot pixel pattern of static displayed when no transmission signal is obtained by the antenna receiver 314 | 315 | ```bash 316 | # if you mess with the -video_size you can have bigger/smaller noise patterns than this. :D 317 | ffmpeg -f rawvideo -pixel_format rgb8 -video_size 640x360 \ 318 | -framerate 60 -i /dev/urandom \ 319 | -f u8 -ar 48100 -ac 1 -i /dev/urandom \ 320 | -sws_flags neighbor -s 640x360 urandom.mp4 321 | ``` 322 | 323 | ![old tv noise](https://upload.wikimedia.org/wikipedia/commons/a/a8/TV_noise.jpg) 324 | 325 | 326 | ## FFmpeg generating video from FFmpeg binary program 327 | 328 | ```bash 329 | # you can replace the binary by any large binary chunk of data (library...) 330 | ffmpeg -f rawvideo -pixel_format rgb8 -video_size 32x23 \ 331 | -framerate 60 -i /usr/local/Cellar/ffmpeg/4.3_2/bin/ffmpeg \ 332 | -f u8 -ar 48100 -ac 1 -i /usr/local/Cellar/ffmpeg/4.3_2/bin/ffmpeg \ 333 | -sws_flags neighbor -s 640x360 -t 5s -pix_fmt yuv420p ffmpeg.mp4 334 | ``` 335 | 336 | ## FFmpeg generating video from Mandelbrot set 337 | 338 | ```bash 339 | ffplay -f lavfi -i mandelbrot=size=640x320:rate=60 \ 340 | -vf "drawtext = text = 'UTC %{gmtime}':fontsize=24:fontcolor=white:boxcolor=black@0.5:x=(w-text_w)/2:y=4:box=1:boxborderw=5" 341 | ``` 342 | -------------------------------------------------------------------------------- /run_live_vp9_ffmpeg_chk_generation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | rm -rf *chk 5 | rm -rf *hdr 6 | rm -rf *mpd 7 | 8 | finish() 9 | { 10 | rm -rf *chk 11 | rm -rf *mpd 12 | rm -rf *hdr 13 | cd - 14 | } 15 | 16 | trap finish EXIT 17 | 18 | VP9_LIVE_PARAMS="-speed 6 -tile-columns 4 -frame-parallel 1 -threads 8 -static-thresh 0 -max-intra-rate 300 -deadline realtime -lag-in-frames 0 -error-resilient 1" 19 | 20 | wget -q https://github.com/0xType/0xProto/releases/download/2.100/0xProto_2_100.zip -O fonts.zip 21 | unzip -o fonts.zip 22 | 23 | docker run --rm -v /tmp/fonts/:/usr/share/fonts -v /tmp/:/files jrottenberg/ffmpeg:4.4-alpine -hide_banner \ 24 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 25 | -f lavfi -i "sine=frequency=1000:sample_rate=48000" \ 26 | -map 0:0 \ 27 | -c:v libvpx-vp9 \ 28 | -keyint_min 60 -g 60 ${VP9_LIVE_PARAMS} \ 29 | -b:v 1400k -bufsize 2800k \ 30 | -vf "drawtext=text='Source > FFmpeg 31 | Codecs > VP9/Opus 32 | Name > Dash Live Streaming 33 | UTC > %{localtime} 34 | Frame > %{frame_num}':box=1:boxborderw=10:x=(w-text_w)/2:y=(h-text_h)/2:fontsize=42:fontcolor=black" \ 35 | -f webm_chunk \ 36 | -header "/files/glass_360.hdr" \ 37 | -chunk_start_index 1 \ 38 | /files/glass_360_%d.chk \ 39 | -map 1:0 \ 40 | -c:a libvorbis \ 41 | -b:a 128k -ar 48000 \ 42 | -f webm_chunk \ 43 | -audio_chunk_duration 2000 \ 44 | -header /files/glass_171.hdr \ 45 | -chunk_start_index 1 \ 46 | /files/glass_171_%d.chk 47 | -------------------------------------------------------------------------------- /run_live_vp9_ffmpeg_dash_mpd_generation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | docker run --rm -v /tmp/:/files jrottenberg/ffmpeg:4.4-alpine -hide_banner \ 6 | -y \ 7 | -f webm_dash_manifest -live 1 \ 8 | -i /files/glass_720.hdr \ 9 | -f webm_dash_manifest -live 1 \ 10 | -i /files/glass_360.hdr \ 11 | -f webm_dash_manifest -live 1 \ 12 | -i /files/glass_audio.hdr \ 13 | -c copy \ 14 | -map 0 -map 1 -map 2 \ 15 | -f webm_dash_manifest -live 1 \ 16 | -adaptation_sets "id=0,streams=0,1 id=1,streams=2" \ 17 | -chunk_start_index 1 \ 18 | -chunk_duration_ms 2000 \ 19 | -time_shift_buffer_depth 7200 \ 20 | -minimum_update_period 7200 \ 21 | /files/glass_live_manifest.mpd 22 | 23 | -------------------------------------------------------------------------------- /short_bbb.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandromoreira/live-stream-from-desktop/6a8619f6a0ead4bb577a76dfd13d561a7e9843f5/short_bbb.mp4 -------------------------------------------------------------------------------- /start_dash_abr_live_stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | rm -rf *m4s 8 | cd - 9 | } 10 | 11 | trap finish EXIT 12 | 13 | docker run --rm -v /tmp/:/files jrottenberg/ffmpeg:4.1 -hide_banner \ 14 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 15 | -f lavfi -i "sine=frequency=1000:sample_rate=48000" \ 16 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 17 | -b:v:0 1400k -bufsize 2800k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 18 | -b:v:1 700k -s:v:1 640:360 -bufsize 1500k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 19 | -map 0:v:0 -map 0:v:0 \ 20 | -c:a libfdk_aac -profile:a aac_low -b:a 64k \ 21 | -map 1:a:0 \ 22 | -f dash -use_timeline 1 -use_template 1 -seg_duration 5 -window_size 250 \ 23 | -utc_timing_url "https://time.akamai.com/?iso" \ 24 | -adaptation_sets "id=0,streams=0,1 id=2,streams=a" \ 25 | /files/out.mpd 26 | -------------------------------------------------------------------------------- /start_hls_abr_live_stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | rm -rf vs*/*ts 8 | rm -rf vs*/*m3u8 9 | rm -rf master.m3u8 10 | cd - 11 | } 12 | 13 | trap finish EXIT 14 | 15 | docker run --rm -v /tmp/:/files jrottenberg/ffmpeg:4.1 -hide_banner \ 16 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30,format=yuv420p" \ 17 | -f lavfi -i "sine=frequency=1000:sample_rate=48000" \ 18 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 19 | -b:v:0 1400k -bufsize 2800k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 20 | -b:v:1 700k -s:v:1 640:360 -bufsize 1500k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 21 | -map 0:v:0 -map 0:v:0 \ 22 | -c:a libfdk_aac -profile:a aac_low -b:a 64k \ 23 | -map 1:a:0 \ 24 | -f hls -hls_time 5 -hls_list_size 50 -var_stream_map "v:0,a:0 v:1,a:0" -master_pl_name master.m3u8 \ 25 | -hls_segment_filename '/files/vs%v/file_%03d.ts' /files/vs%v/out.m3u8 26 | -------------------------------------------------------------------------------- /start_hls_abr_live_stream_file_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | rm -rf vs*/*ts 8 | rm -rf vs*/*m3u8 9 | rm -rf master.m3u8 10 | cd - 11 | } 12 | 13 | trap finish EXIT 14 | 15 | docker run --rm -v /tmp/:/files jrottenberg/ffmpeg:4.1 -hide_banner \ 16 | -re -stream_loop -1 -i /files/short_bbb.mp4 \ 17 | -c:v libx264 -preset ultrafast -tune zerolatency -profile:v high \ 18 | -b:v:0 2400k -bufsize 2800k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 19 | -b:v:1 1400k -s:v:1 640:360 -bufsize 1700k -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 20 | -map 0:v:0 -map 0:v:0 \ 21 | -c:a libfdk_aac -profile:a aac_low -b:a 128k \ 22 | -map 0:a:0 \ 23 | -f hls -hls_time 5 -hls_list_size 50 -var_stream_map "v:0,a:0 v:1,a:0" -master_pl_name master.m3u8 \ 24 | -hls_segment_filename '/files/vs%v/file_%03d.ts' /files/vs%v/out.m3u8 25 | -------------------------------------------------------------------------------- /start_hls_low_latency_live_stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | rm -rf *ts 8 | rm -rf *m3u8 9 | rm -rf OpenSans-Bold.ttf 10 | cd - 11 | } 12 | 13 | trap finish EXIT 14 | 15 | wget -q https://raw.githubusercontent.com/google/fonts/main/apache/opensanscondensed/OpenSansCondensed-Bold.ttf -O OpenSans-Bold.ttf 16 | 17 | docker run --rm -v $(pwd):/files jrottenberg/ffmpeg:4.1 -hide_banner \ 18 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30" -pix_fmt yuv420p \ 19 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 20 | -tune zerolatency -profile:v high -preset veryfast -bf 0 -refs 3 \ 21 | -b:v 1400k -bufsize 1400k \ 22 | -vf "drawtext=fontfile='/files/OpenSans-Bold.ttf':text='%{localtime}:box=1:fontcolor=black:boxcolor=white:fontsize=100':x=40:y=400'" \ 23 | -hls_time 1 -hls_list_size 240 -hls_start_number_source epoch -f hls /files/stream.m3u8 24 | -------------------------------------------------------------------------------- /start_http_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | cd - 8 | } 9 | 10 | trap finish EXIT 11 | 12 | docker run --rm -v $(pwd):/opt/www -p 8080:8080 webratio/nodejs-http-server:0.9.0 http-server /opt/www -a :: -p 8080 --cors -c-1 13 | -------------------------------------------------------------------------------- /start_mpeg_dash_low_latency_live_stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /tmp/ 4 | 5 | finish() 6 | { 7 | rm -rf *m4s 8 | rm -rf *mpd 9 | rm -rf OpenSans-Bold.ttf 10 | cd - 11 | } 12 | 13 | trap finish EXIT 14 | 15 | wget -q https://raw.githubusercontent.com/google/fonts/main/apache/opensanscondensed/OpenSansCondensed-Bold.ttf -O OpenSans-Bold.ttf 16 | 17 | docker run --rm -v $(pwd):/files jrottenberg/ffmpeg:4.1 -hide_banner \ 18 | -re -f lavfi -i "testsrc2=size=1280x720:rate=30" -pix_fmt yuv420p \ 19 | -c:v libx264 -x264opts keyint=30:min-keyint=30:scenecut=-1 \ 20 | -tune zerolatency -profile:v high -preset veryfast -bf 0 -refs 3 \ 21 | -b:v 1400k -bufsize 1400k \ 22 | -vf "drawtext=fontfile='/files/OpenSans-Bold.ttf':text='%{localtime}:box=1:fontcolor=black:boxcolor=white:fontsize=100':x=40:y=400'" \ 23 | -utc_timing_url "https://time.akamai.com/?iso" -use_timeline 0 -media_seg_name 'chunk-stream-$RepresentationID$-$Number%05d$.m4s' \ 24 | -init_seg_name 'init-stream1-$RepresentationID$.m4s' \ 25 | -window_size 5 -extra_window_size 10 -remove_at_exit 1 -adaptation_sets "id=0,streams=v id=1,streams=a" -f dash /files/stream.mpd 26 | --------------------------------------------------------------------------------