I have been writing a program to automatically transcode and package videos for adaptive bitrate streaming in MPEG-DASH format.
The program seemed to be handling all video files correctly, generating all the mpd manifests and segment files as expected, until I encountered that one specific video file (classic, right?).
The video file did not throw error or anything during the transcoding and packaging process, but when I implemented the bitrate switching functionality in the frontend, the issue presented itself:
For this particular video, there should be 720p, 480p, and 360p resolutions available, but the video player only detected 480p.
tl;dr
The issue was caused by MP4Box treating the 480p video incompatible with the other resolutions due to the Display Aspect Ratio.
Adding the option -vf "setdar=<aspect-ratio>"
solved the issue. For example:
|
|
Manifest file
Naturally, the first thing I did was to check the generated manifest file. Something interesting was happening there:
|
|
It took me a while to realize that the par
(Display Aspect Ratio) was different for the two adaptation sets. The 480p video had par="427:240"
while the others had par="16:9"
, which made them incompatible.
For most of the other videos with the same resolution, ffmepg automatically generated the par
value as 16:9
. I’m still not sure why this video along with a few others had a different par
value only for 480p.
Fixing the code
I was using a Go function like below to transcode the video:
|
|
And the fix was simple: ffmpeg supports setting the Display Aspect Ratio (DAR) explicitly with the setdar
filter.
|
|
The dar
parameter comes from the aspect ratio of the source video, simplified using a simple Euclidean algorithm.
|
|
|
|
Fixed
Feels good.