如何将 F4F 文件转换为 MP4?

Posted

技术标签:

【中文标题】如何将 F4F 文件转换为 MP4?【英文标题】:How to convert F4F file to MP4? 【发布时间】:2012-03-06 19:28:50 【问题描述】:

我们知道 F4F 是 Adob​​e 用于 HTTP 动态流 的分段 MP4 文件格式。 F4F Packager 工具可以将一个 F4V 文件转换为多个 F4F 文件和一个清单文件(F4M)。

我的问题是,如何将此类 F4F 文件转换回 F4V 或 MP4 文件?

【问题讨论】:

我对捕获这些流的工具更感兴趣。 【参考方案1】:

我们终于找到了一个简单的方法来合并和转换.f4f文件->.flv文件,其中只有'mdat'框有用。这是一个php代码:

<?php
  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++;
      else
          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";
?>

【讨论】:

你到底做了什么?你写了一个标题然后只合并了 mdat 部分? 无法让它工作。首先没有hex2bin函数,ReadInt32函数无效。我修复了所有这些,但仍然有问题。我认为我的文件是一个 64 位 mdat 片段,因为 mdat 之前的前 4 个字符是 00 00 00 01,这显然不是 mdat 的大小。 正则表达式需要 s 修饰符:(.4)mdat[\x08\x09\x12]/is $fragCount + 1 括在括号中以避免错误处理某些包含数字的文件名。 我们可以做得比 PHP 更好。【参考方案2】:

此处提供更全面的答案:https://github.com/K-S-V/Scripts/blob/master/AdobeHDS.php。

严重的事情发生在around line 1046。 此脚本处理比当前最佳答案更多的情况。篇幅有点长,这里就不放全文了。

唉,它也是一个 PHP 脚本,不过我可能需要在几周内用 Java 重写它。如果是这样,我会在完成后发布 Java 重写的链接。

【讨论】:

使用适合我的脚本:php AdobeHDS.php --fragments Seg1-Frag(我的 f4f 文件是:Seg1-Frag1Seg2-Frag2 等) 在 FireFox 中使用 HDS Link Detector 插件可以更轻松地使用此脚本。我让插件生成正确的命令,将其粘贴到控制台,然后以这种方式运行。【参考方案3】:

livestreamer 和 youtube-dl 都支持 HDS 流。这是一个直播者的例子:

$ livestreamer -O 'hds://radio_chym-lh.akamaihd.net/z/KIT967_1@183249/manifest.f4m' 48k >out.m4a

这是一个网络电台。对于视频,只需更改48kout.m4a 的文件扩展名即可。

【讨论】:

以上是关于如何将 F4F 文件转换为 MP4?的主要内容,如果未能解决你的问题,请参考以下文章

如何将目录中的多个 .dav 文件转换为 .mp4 [重复]

如何使用 bash 命令或 Ruby 使用 ffmpeg 将 mp4 文件批量转换为 ogg

如何将flv格式转换成mp4格式

如何将下载多个m3u8的小视频合并转换为MP4或是其他完整的视频?????

使用ffmpeg将文件夹中的所有mp4音频文件转换为mp3 [重复]

如何将 mp4 转换为 NSData?