2012-02-15 20 views
20

Sabemos que F4F es el formato de archivo MP4 fragmentado de Adobe para HTTP Dynamic Streaming. Una herramienta llamada F4F Packager podría convertir un archivo F4V a varios archivos F4F y un archivo de manifiesto (F4M).Cómo convertir un archivo F4F a MP4?

Mi pregunta es, ¿cómo convertir esos archivos F4F a un archivo F4V o MP4?

+1

Tendría más interés en una herramienta que capture estas transmisiones. – palswim

Respuesta

10

Finalmente encontramos un método sencillo para combinar & convertir archivos .f4f -> .flv presentar, en el que sólo cuadro 'mdat' es muy útil. Aquí es un código del 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"; 
?> 
+0

¿Qué hiciste exactamente? ¿Escribió un encabezado y luego fusionó solo la sección mdat? –

+0

No se pudo hacer que esto funcione. En primer lugar, no hay función hex2bin, la función ReadInt32 no es válida. Solucioné todos estos pero todavía tenía un problema. Creo que mi archivo es un fragmento mdat de 64 bits, ya que los primeros 4 caracteres antes de mdat son 00 00 00 01, lo que obviamente no es del tamaño de mdat. – Craig

+0

La expresión regular necesita el modificador s: (. {4}) mdat [\ x08 \ x09 \ x12]/es – marlar

10

Una respuesta más completa está disponible aquí: https://github.com/K-S-V/Scripts/blob/master/AdobeHDS.php.

Las cosas serias pasan around line 1046. Este script maneja más casos que la respuesta superior actual. No publicaré todo el script aquí porque es un poco largo.

Por desgracia, también es un script PHP, aunque podría necesitar volver a escribir esto en Java en un par de semanas. Si es así, publicaré un enlace a la reescritura de Java cuando esté listo.

+0

alguna actualización para esto? –

+1

Usar el script funcionó para mí: 'php AdobeHDS.php --fragmentos Seg1-Frag' (mis archivos f4f eran:' Seg1-Frag1', 'Seg2-Frag2', etc.) – dusan

+0

Realmente funciona bien, gracias (+ 1). –

0

livestreamer y youtube-dl son compatibles con transmisiones HDS. Aquí hay un ejemplo de livestreamer:

$ livestreamer -O 'hds://radio_chym-lh.akamaihd.net/z/[email protected]/manifest.f4m' 48k >out.m4a 

Esta es una estación de radio por Internet. Para video, solo un cambio en 48k y la extensión de archivo out.m4a deberían ser necesarios.

Cuestiones relacionadas