2012-02-15 29 views
20

Sappiamo che F4F è il formato file MP4 frammentato di Adobe per HTTP Dynamic Streaming. Uno strumento chiamato F4F Packager potrebbe convertire un file F4V in diversi file F4F e un file manifest (F4M).Come convertire il file F4F in MP4?

La mia domanda è, come convertire tale F4F i file di nuovo ad un file F4V o MP4?

+1

Avrei più interesse per uno strumento che catturasse questi flussi. – palswim

risposta

10

abbiamo finalmente trovato un metodo semplice per unire & convertire file .f4f -> .flv presentare, in cui solo box 'mdat' è utile. Qui è un codice 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

Cosa hai fatto esattamente? Hai scritto un'intestazione quindi hai unito solo la sezione mdat? –

+0

Impossibile farlo funzionare. Innanzitutto non esiste una funzione hex2bin, la funzione ReadInt32 non è valida. Ho risolto tutti questi problemi ma ho ancora avuto un problema. Penso che il mio file sia un frammento mdat a 64 bit come il primo 4 carattere prima che mdat sia 00 00 00 01 che ovviamente non è la dimensione del mdat. – Craig

+0

L'espressione regolare ha bisogno del modificatore s: (. {4}) mdat [\ x08 \ x09 \ x12]/è – marlar

10

Una risposta più completa è disponibile qui: https://github.com/K-S-V/Scripts/blob/master/AdobeHDS.php.

Le cose serie si verificano around line 1046. Questo script gestisce più casi che la risposta superiore corrente. Non posterò l'intero script qui poiché è un po 'lungo.

Ahimè, è uno script PHP troppo, anche se posso avere bisogno di riscrivere questo in Java in un paio di settimane. Se è così, pubblicherò un link per la riscrittura di Java quando è fatto.

+0

eventuali aggiornamenti per questo? –

+1

utilizzando lo script ha lavorato per me: 'php AdobeHDS.php --fragments segm1-Frag' (i miei file F4F erano:' segm1-Frag1', 'SEG2-Frag2', etc.) – dusan

+0

funziona davvero bene, grazie (+ 1). –

0

livestreamer e youtube-dl supportano entrambi i flussi HDS. Ecco un esempio di livestreamer:

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

Questa è una stazione radio internet. Per i video, dovrebbe essere necessaria solo una modifica in 48k e l'estensione del file di out.m4a.

Problemi correlati