如何使用FFMPEG将H264正确包装到FLV中?

如何使用FFMPEG将H264正确包装到FLV中?,ffmpeg,h.264,flv,Ffmpeg,H.264,Flv,首先,标题中的“适当”指的是,其中的答案并不能解决我的问题 tl;dr:对视频进行编码和将其直接存储到FLV中以及分两个单独的步骤完成这两个步骤是有区别的。我需要单独做,如何获得与直接做相同的结果 Nvidia的硬件编码器NVENC在没有容器的情况下生成原始H.264数据,这在大多数视频播放器中很难播放。对于Adobe AIR应用程序,我需要将视频包装为FLV格式,我希望使用FFMPEG: ffmpeg -f h264 -i "input.h264" -c copy -f flv "output

首先,标题中的“适当”指的是,其中的答案并不能解决我的问题

tl;dr:对视频进行编码和将其直接存储到FLV中以及分两个单独的步骤完成这两个步骤是有区别的。我需要单独做,如何获得与直接做相同的结果

Nvidia的硬件编码器NVENC在没有容器的情况下生成原始H.264数据,这在大多数视频播放器中很难播放。对于Adobe AIR应用程序,我需要将视频包装为FLV格式,我希望使用FFMPEG:

ffmpeg -f h264 -i "input.h264" -c copy -f flv "output.flv"
这并没有像预期的那样起作用,因为以这种方式处理的每个视频的第一帧根本没有显示。每个视频仅从第二帧显示,这对于单帧视频来说是一个耻辱(仅使用GPU的硬件编码器进行闪电般快速的图像压缩)

为了便于检查,我现在对输入视频重新编码两次:一次直接到FLV输出

ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f flv "A.flv"
一次转到H.264,然后将其推入FLV

ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f h264 "reencode.h264"
ffmpeg -f h264 -i "reencode.h264" -c copy -f flv "B.flv"
第一个视频播放正常,第二个视频播放不正常。直接方法产生的FLV(A.FLV,见下文)的文件结构略有不同,尤其是NAL单元不同,我怀疑这是导致不同行为的原因

所以,我的问题是:如果我已经有了一个H.264视频,并且只想将它复制到FLV容器中而不进行转码,但是文件和帧头应该像实际转码时那样正确填写,我该如何告诉FFMPEG?是否有用于此的命令,例如“-c copy butGenerateValidHeader”

以下是文件的相关部分:

直接法

ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f flv "A.flv"
A.flv

先编码

ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f h264 "reencode.h264"
reencode.h264

00 00 00 01 67 4D 40 20 95 A0 13 81 F7 EB 01 10 // Sequence parameter set
00 00 3E 80 00 0E A6 08 F1 C3 2A
                                 00 00 00 01 68 // Picture parameter set
EE 3C 80
         00 00 00 01 65                         // IDR frame
                       [B8 04 1D FF ...]        // Frame data
挤进集装箱

ffmpeg -f h264 -i "reencode.h264" -c copy -f flv "B.flv"
B.flv

2017年8月8日更新:添加了用于检查的输入和输出文件

    • (1)

      “如果我已经有一个H.264视频,只想将其复制到 FLV容器未进行转码,但文件和帧头 应该像实际转码时一样正确填写, 我该如何告诉FFMPEG?”

      您需要muxing:尝试下面的命令(直接将H.264数据复制到FLV容器中)

      (二)

      以这种方式处理的每个视频的第一帧根本不显示。每个 视频仅从第二帧开始显示,这让人感到羞耻 单帧视频

      您如何检查帧以确定它仅显示第2帧之后的帧?是通过AS3 code
      netStream.pause()
      还是通过VLC等媒体播放器

      在FLV中,每个视频帧进入
      视频标签
      。对于其他编解码器,我们可以说将帧1放入视频标签1等。。但是对于H.264,第一个标签始终保存“AVC解码器配置”数据,因此输入视频帧1的像素将存在于FLV的视频标签2处
      还有你的第一个显示字节。。。在“AVC NALU”部分中,
      17 01
      让您知道这是一个关键帧(第一帧始终是一个关键帧),如果第二帧(通常是P帧)没有在第一个解码关键帧(I帧),MPEG解码器将永远不会显示第二帧(通常是P帧)。你的帧1图像存在于某处


      我无法用某个时间码倒计时的H.264视频重现此问题。第一帧开始于
      00hh:00mm:00ss:00msec
      ,msec逐帧向上移动。在使用第(1)点所示的命令后,如果我使用
      appendBytes
      仅向解码器提供单个帧的数据(
      byteArray
      打包为1帧FLV),我会在VLC和MPC-HC以及AS3中看到第一帧。

      首先,您对文件结构的描述与二进制文件a.FLV和B.FLV中的实际结构相矛盾(它们是向后的)。那么您真正想要哪个结果呢?比如A.flv和起始代码:
      00 01 67..00 00 01 68..00 00 00 01 65
      或者B.flv和avcC+
      00 17 67..00 04 68..00 01 94 91 65

      FLV的标准格式类似于带有avcC的B.FLV(无起始代码),默认情况下,它是通过以下方式生成的:
      ffmpeg-i“reencode.h264”-c copy“c.FLV”
      :如下所示


      如果这个文件对你有用,那就尝试更新你的ffmpeg(我使用的是master branch的自编版本)。至于起始代码的格式,我不知道如何生成它们。

      你介意分享你的各种视频文件吗?试试
      ffmpeg-f h264-I“reencode.h264”-c copy-bsf:v extract\u extradata-f flv“B.flv”
      命令行,即使用extract_extradata bitstream filter。@Markus Schumann:我在问题的末尾添加了文件。@nobody555:谢谢你的提示,但它不起作用。视频不仅不会在Adobe AIR中显示,也不会在MPC-HC中显示。首先,你对文件结构的描述与真实结构相矛盾在你的二进制文件A.flv和B.flv中(它们是反向的)。那么你真正想要的结果是A.flv(起始代码:00 00 00 01 67..00 00 00 01 68..00 00 00 00 01 65)还是B.flv(avcC:00 17 67..00 04 68..00 01 94 91 65)?flv的标准格式类似于带有avcC的B.flv(没有起始代码),并且默认情况下是使用:
      ffmpeg-i生成的“reencode.h264”-c copy“c.flv”
      :。如果这对您尝试更新ffmpeg有效。至于起始代码的格式,我不知道如何生成它们。不幸的是,建议的重复播放不起作用。请检查我更新的问题以获得结果视频(“copy.flv”)。虽然它在MPC-HC中播放,但它不会在空中显示(AS3,使用netStream.appendBytes)。
      ffmpeg -f h264 -i "reencode.h264" -c copy -f flv "B.flv"
      
      46 4C 56 01 01 00 00 00 09 00 00 00 00 12 00 00 // FLV header + metadata
      A4 00 00 00 00 00 00 00 02 00 0A 6F 6E 4D 65 74
      61 44 61 74 61 08 00 00 00 07 00 08 64 75 72 61
      74 69 6F 6E 00 3F A4 7A E1 47 AE 14 7B 00 05 77
      69 64 74 68 00 40 93 80 00 00 00 00 00 00 06 68
      65 69 67 68 74 00 40 8E F0 00 00 00 00 00 00 0D
      76 69 64 65 6F 64 61 74 61 72 61 74 65 00 00 00
      00 00 00 00 00 00 00 0C 76 69 64 65 6F 63 6F 64
      65 63 69 64 00 40 1C 00 00 00 00 00 00 00 07 65
      6E 63 6F 64 65 72 02 00 0D 4C 61 76 66 35 37 2E
      37 31 2E 31 30 30 00 08 66 69 6C 65 73 69 7A 65
      00 40 F9 5B 40 00 00 00 00 00 00 09
                                          00 00 00 AF // AVC sequence start
      09 00 00 05 00 00 00 00 00 00 00 17 00 00 00 00
      
      00 00 00 10 09 01 94 BD 00 00 00 00 00 00 00 17 // AVC NALU
      01 00 00
               00 00 00 00 01 67 4D 40 20 95 A0 13 81 // Sequence parameter set
      F7 EB 01 10 00 00 3E 80 00 0E A6 08 F1 C3 2A
                                                   00 // Picture parameter set
      00 00 01 68 EE 3C 80
                           00 00 00 01 65             // IDR frame
                                         [B8 04 1D FF // Frame data
      ...]
      00 01 94 C8 09 00 00 05 00 00 00 00 00 00 00    // ?
                                                   17 // AVC sequence end
      02 00 00 00 00 00 00 10
      
      ffmpeg -i input.h264 -c:v copy output.flv