2012-02-15 4 views
20

Nous savons que F4F est le format de fichier MP4 fragmenté d'Adobe pour HTTP Dynamic Streaming. Un outil appelé F4F Packager peut convertir un fichier F4V en plusieurs fichiers F4F et un fichier manifeste (F4M).Comment convertir un fichier F4F au MP4?

Ma question est, comment convertir de tels fichiers F4F en un fichier F4V ou MP4?

+1

Je m'intéresserais davantage à un outil qui capturerait ces flux. – palswim

Répondre

10

Nous avons finalement trouvé une méthode simple pour fusionner & convertir fichiers .f4f -> fichier .flv, dans lequel seule case « MDAT » est utile. Voici un code 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'avez-vous fait exactement? Vous avez écrit un en-tête puis fusionné seulement la section mdat? –

+0

Impossible de faire fonctionner ceci. Premièrement, il n'y a pas de fonction hex2bin, la fonction ReadInt32 n'est pas valide. J'ai réparé tout cela mais j'ai quand même eu un problème. Je pense que mon fichier est un fragment mdat de 64 bits comme le premier 4 caractères avant mdat 00 00 00 01 qui n'est évidemment pas la taille de la mdat. – Craig

+0

La regex a besoin du modificateur s: (. {4}) mdat [\ x08 \ x09 \ x12]/est – marlar

10

Une réponse plus complète est disponible ici: https://github.com/K-S-V/Scripts/blob/master/AdobeHDS.php.

Les choses sérieuses se produisent around line 1046. Ce script gère plus de cas que la première réponse en cours. Je ne vais pas poster tout le script ici car c'est un peu long. Hélas, c'est aussi un script PHP, même si j'ai besoin de le réécrire en Java dans quelques semaines. Si c'est le cas, je posterai un lien vers la réécriture Java quand c'est fait. Livestreamer et youtube-dl supportent tous deux les flux HDS.

+0

des mises à jour pour cela? –

+1

L'utilisation du script a fonctionné pour moi: 'php AdobeHDS.php --fragments Seg1-Frag' (mes fichiers f4f étaient:' Seg1-Frag1', 'Seg2-Frag2', etc.) – dusan

+0

Ça marche vraiment bien, merci (+ 1). –

0

Voici un exemple de livestreamer:

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

Ceci est une station de radio Internet. Pour la vidéo, seul un changement de 48k et l'extension de fichier out.m4a devraient être nécessaires.

Questions connexes