when downloading a vimeo video my downloaded always stopped at 99%. I was left with two collections of m4s files; one for video and one for audio stream.
I tried all possible solutions an none worked for me. Renaming the extension to mp4 did not work, concatination with ffmpeg also did not work. I realised that video stream is created by an init.mp4 file followed by other segments one by one. The video player gets the information about the stream quality in a separate file, usually in text format. It then use the init.m4s file with video headers as a started and glues the segments to it in a proper order one by one. The same procedure applies to audio stream as well.
I found this solution using developer tools of the browser, hexeditor and ffmpeg:
- open the page with a video and open developer tools (CTRL-SHIFT-C in firefox)
- press play in video player and monitor network traffic in developer tools.
- a found a json file with information and save it to disk
The file had all the information about streams. There were descriptions for five video streams and three audio streams. Stream for a video 1280x720 looked like this:
{
"id": "b522db58",
"base_url": "video/",
"format": "dash",
"mime_type": "video/mp4",
"codecs": "avc1.640020",
"bitrate": 2895000,
"avg_bitrate": 1068000,
"duration": 6787.88,
"framerate": 25,
"width": 1280,
"height": 720,
"max_segment_duration": 7,
"init_segment": "AAAAIGZ0eXBkYXNoAAAAAGRhc2htcDQybXA0MWlzbzYAAAMfbW9vdgAAAGxtdmhkAAAAAN+RBZPfkQWTAAAAGQAAAAAAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpb2RzAAAAABCAgIAQAE////9//w6AgIAEAAAAAQAAAk50cmFrAAAAXHRraGQAAAAH35EFk9+RBZMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAABQAAAALQAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAAAAAAAAwABAAAAAAHGbWRpYQAAACBtZGhkAAAAAN+RBZPfkQWTAAAAGQAAAABVxAAAAAAANmhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABMLVNNQVNIIFZpZGVvIEhhbmRsZXIAAAABaG1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAShzdGJsAAAAsHN0c2QAAAAAAAAAAQAAAKBhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAABQAC0ABIAAAASAAAAAAAAAABCkFWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAN2F2Y0MBZAAg/+EAG2dkACCs2YBQBbpqAgICgAAAAwCAAAAZB4wYzQEABWjpeyyL/fj4AAAAABNjb2xybmNseAABAAEAAQAAAAAQc3R0cwAAAAAAAAAAAAAAEHN0c2MAAAAAAAAAAAAAABRzdHN6AAAAAAAAAAAAAAAAAAAAEHN0Y28AAAAAAAAAAAAAABhzZ3BkAQAAAHJvbGwAAAACAAAAAAAAABRzYmdwAAAAAHJvbGwAAAAAAAAAPG12ZXgAAAAUbWVoZAEAAAAAAAAAAAKW4QAAACB0cmV4AAAAAAAAAAEAAAABAAAAAQAAAAAAAQAA",
"index_segment": "b522db58.mp4?r=dXMtd2VzdDE%3D&range=831-14434",
"segments": [
{
"start": 0,
"end": 6.08,
"url": "b522db58.mp4?r=dXMtd2VzdDE%3D&range=14435-328375",
"size": 313940
},
{
- create a file video_start.mp4 with a value of init_segmet and decode64 it with https://www.base64decode.org/ . This is our init.m4s starter.
- use hex editor and concatenade video_start.mp4 with all other .m4s files in the right order. (Tools -> File tools -> concatenate). Save as video.mp4
You can identify the right segments by looking a their size
- repeat the same procedure for audio stream:
"audio": [
{
"id": "d27f1f72",
"base_url": "audio/",
"format": "dash",
"mime_type": "audio/mp4",
"codecs": "mp4a.40.2",
"bitrate": 191000,
"avg_bitrate": 191000,
"duration": 6787.84,
"channels": 2,
"sample_rate": 48000,
"max_segment_duration": 8,
"init_segment": "AAAAIGZ0eXBkYXNoAAAAAGRhc2htcDQybXA0MWlzbzYAAAKmbW9vdgAAAGxtdmhkAAAAAN+RBlHfkQZRAAC7gAAAAAAAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpb2RzAAAAABCAgIAQAE///yn//w6AgIAEAAAAAQAAAdV0cmFrAAAAXHRraGQAAAAH35EGUd+RBlEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAETa5AAAAAAAAABAAAAAAFNbWRpYQAAACBtZGhkAAAAAN+RBlHfkQZRAAC7gAAAAABVxAAAAAAANmhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABMLVNNQVNIIEF1ZGlvIEhhbmRsZXIAAAAA721pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAAs3N0YmwAAABnc3RzZAAAAAAAAAABAAAAV21wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAC7gAAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAVAAAAAAAAAAAAAAAFgICAAhGQBoCAgAECAAAAEHN0dHMAAAAAAAAAAAAAABBzdHNjAAAAAAAAAAAAAAAUc3RzegAAAAAAAAAAAAAAAAAAABBzdGNvAAAAAAAAAAAAAAA8bXZleAAAABRtZWhkAQAAAAAAAAATa5AAAAAAIHRyZXgAAAAAAAAAAQAAAAEAAAABAAAAAAABAAA=",
"index_segment": "d27f1f72.mp4?r=dXM%3D&range=710-14325",
"segments": [
{
"start": 0,
"end": 5.994666666666666,
"url": "d27f1f72.mp4?r=dXM%3D&range=14326-157787",
"size": 143461
},
create a file audio_start.mp4 with a value of init_segmet and decode64 it with https://www.base64decode.org/ .
Concatenade audio_start.mp4 with all other .m4s files in the right order. (Tools -> File tools -> concatenate). Save as audio.mp4
use ffmpeg and join both streams
ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4
- done