Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
We know F4F is Adobe's fragmented MP4 file format for
HTTP Dynamic Streaming
. A tool called
F4F Packager
could convert an F4V file to several F4F files and a manifest file(F4M).
My question is, how to convert such F4F files back to an F4V or MP4 file?
We finally found a simple method to merge & convert
.f4f files -> .flv file
, in which only 'mdat' box is usefull. Here is a the php code:
function ReadInt24($str, $pos)
return intval(bin2hex(substr($str, $pos, 3)), 16);
function ReadInt32($str, $pos)
return unpack("N", substr($str, $pos, 4))[1];
echo "\nKSV Adobe HDS Downloader\n\n";
$flvHeader = hex2bin("464c5601050000000900000000");
$firstVideoPacket = true;
$prevTagSize = 4;
$fragCount = 0;
isset($argv[1]) ? $baseFilename = $argv[1] : $baseFilename = "";
$baseFilename ? $outputFile = "$baseFilename.flv" : $outputFile = "Joined.flv";
while (true)
if (file_exists("$baseFilename" . $fragCount + 1 . ".f4f"))
$fragCount++;
break;
echo "Found $fragCount fragments\n";
$flv = fopen("$outputFile", "wb");
fwrite($flv, $flvHeader, 13);
for ($i = 1; $i <= $fragCount; $i++)
$frag = file_get_contents("$baseFilename$i.f4f");
preg_match('/(.{4})mdat[\x08\x09\x12]/i', $frag, $mdat, PREG_OFFSET_CAPTURE);
$fragLen = ReadInt32($mdat[1][0], 0) - 8;
$frag = substr($frag, $mdat[1][1] + 8, $fragLen);
$pos = 0;
while ($pos < $fragLen)
$packetType = $frag[$pos];
$packetSize = ReadInt24($frag, $pos + 1);
$packetTS = ReadInt24($frag, $pos + 4);
$totalTagLen = 11 + $packetSize + $prevTagSize;
if (($packetType == "\x08" && $packetSize > 4) or ($packetType == "\x09" && $packetSize > 40) or ($packetType == "\x09" && $firstVideoPacket))
if ($packetType == "\x09" && $firstVideoPacket)
$firstVideoPacket = false;
fwrite($flv, substr($frag, $pos, $totalTagLen), $totalTagLen);
$pos += $totalTagLen;
fclose($flv);
echo "Finished\n";
–
–
A more comprehensive answer is available here :
https://github.com/K-S-V/Scripts/blob/master/AdobeHDS.php
.
The serious stuff happens
around line 1046
.
This script handles more cases that the current top answer. I won't post the whole script here since it's a bit long.
Alas, it's a PHP script too, though I may need to rewrite this in Java in a couple of weeks. If so, I'll post a link to the Java rewrite when it's done.
–
–
livestreamer and youtube-dl both support HDS streams. Here's an example of livestreamer:
$ livestreamer -O 'hds://radio_chym-lh.akamaihd.net/z/KIT967_1@183249/manifest.f4m' 48k >out.m4a
This is an internet radio station. For video, only a change in 48k
and the file extension of out.m4a
should be necessary.