FFMpeg Low Latency DASH

Low Latency DASH allows the reduction of glass-to-glass latency to around 2-3 seconds with affordability and scalability in mind.

The reasons for high latency:

  1. Encoder needs a buffer to encode video efficiently.

  2. Video segments must be uploaded to the Origin server to be available for download.

  3. CDN must get a video segment from the Origin, cache it, and start transferring it to the client’s video player.

  4. Player must cache at least a few segments to begin video playback.

To address those issues we will:

  1. Tune FFMpeg to encode video with as little delay as possible using the -tune zerolatency parameter.

  2. Tebi DataStream protocol accepts Chunked Encoded PUT uploads and makes them immediately available, even before the upload is complete. Readers will receive the data almost as fast as it is being uploaded by the encoder to the storage.

  3. By eliminating CDN altogether, the latency factor is entirely removed from the equation, making our system faster and simpler. Tebi geo-distributed object storage is capable of quickly, efficiently, and inexpensively delivering data to all corners of the world.

  4. By making video chunks smaller, we reduce latency significantly. However, reducing latency makes the player more susceptible to interruptions due to various network conditions.

  5. Common Media Application Format (CMAF) employs chunked encoding and chunked transfer encoding to lower latency.

Prepare Your Tebi Account

Create a bucket to store our DASH video stream.

FFMpeg will write DASH stream directly into this bucket. Let’s name it ffmpeg-dash-test.

For simplicity, let’s configure the bucket default permission (ACL) to Public – this will make all files that FFMpeg puts into the bucket publicly accessible without a signature.

Open “bucket preferences” and click the Access Control tab. Select Public for the DataStream Default ACL option and save the form by clicking the Update button. Allow FFMpeg to write to the bucket without authentication.

Then, open “bucket preferences” again and select the Bucket Policy tab. Check the Enable checkbox to enable Policy for this bucket, and input the following JSON policy into the JSON field:

 1{
 2  "Version": "2012-10-17",
 3  "Id": "FFMpeg",
 4  "Statement": [
 5    {
 6      "Sid": "DSAllow",
 7      "Effect": "Allow",
 8      "Action": [
 9        "ds:PutObject", "ds:DeleteObject"
10      ],
11      "Resource": "*",
12      "Condition": {}
13    }
14  ]
15}

Save the form. Now, we have a bucket that is ready to receive data from FFMpeg and distribute it to clients for unrestricted playback. This is a very simple Bucket Policy example. For the production deployment, we suggest you limit this policy by IP address so that only you can upload and delete data in the bucket. You can read more about Bucket Policy here.

If you plan to play your stream in the web player from a different domain, enable Cross-Origin Resource Sharing (CORS) to allow your web-browser JavaScript code to access resources located in your bucket. To do this, open bucket preferences, select the CORS tab, and check the Enable checkbox to enable CORS for all domains – leave the XML textbox blank. Now, save the form to apply changes. You can read more about Bucket CORS here.

The player might request a chunk that the encoder has not started uploading to Tebi Storage and is therefore not yet ready. To avoid an error, we can ask Tebi to wait for a file for a given amount of time and start its streaming once the encoder begins upload. To do this, open “bucket preferences” and click the Advanced tab. Set the DataStream - wait for an object parameter to 500 ms. Save the form by clicking the Update button.

FFMpeg Command Line Parameters

ffmpeg -re -fflags +genpts -i https://s3.tebi.io/test/examples/bbb_1080p_30fps.mp4 \
-pix_fmt yuv420p -c:v libx264 -c:a copy -b:v 5000K -g:v 30 -keyint_min:v 30 -sc_threshold:v 0 \
-preset veryfast -tune zerolatency \
-adaptation_sets 'id=0,seg_duration=2.002,streams=v id=1,seg_duration=2.002,streams=a' \
-use_timeline 0 -streaming 1 -window_size 3 -frag_type every_frame -flags +global_header \
-ldash 1 -utc_timing_url 'https://time.akamai.com?iso&ms' \
-format_options 'movflags=cmaf' -timeout 0.5 -write_prft 1 -target_latency '3.0' \
-http_persistent 1 -method PUT \
-f dash https://ffmpeg-dash-test.datastream.tebi.io/dash/test.mpd

After FFMpeg has started, give it a moment to prepare and upload the first few video segments to the storage. You can watch your stream using the DASH.js player here: https://reference.dashif.org/dash.js/latest/samples/index.html. Use the following: Manifest URL https://ffmpeg-dash-test.datastream.tebi.io/dash/test.mpd.

See Also