如何使用FFMPEG将H264正确包装到FLV中? [英] How to properly wrap H264 into FLV with FFMPEG?

查看:108
本文介绍了如何使用FFMPEG将H264正确包装到FLV中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,标题中的正确"是指

First of all, the "properly" in the title refers to this related question, of which answer does not solve my problem.

tl; dr:对视频进行编码并将其直接存储到FLV并在两个单独的步骤中进行操作之间是有区别的.我需要单独进行操作,如何获得与直接进行操作相同的结果?

tl;dr: There is a difference between encoding a video and directly storing it into FLV and doing this in two separate steps. I need to do it separately, how do I get the same result as doing it directly?

Nvidia的硬件编码器NVENC无需容器即可生成原始H.264数据,这在大多数视频播放器中都很难播放.对于Adobe AIR应用程序,我需要将视频包装为FLV格式,为此我想使用FFMPEG:

Nvidia's hardware encoder NVENC produces raw H.264 data without a container, which is difficult to play in most video players. For an Adobe AIR application, I need to wrap the video into the FLV format, for which I wanted to use FFMPEG:

ffmpeg -f h264 -i "input.h264" -c copy -f flv "output.flv"

这没有按预期方式工作,因为只显示了以这种方式处理的每个视频的第一帧.每个视频仅从第二帧开始显示,这对于单帧视频是可耻的(使用GPU的硬件编码器仅实现闪电般快速的图像压缩).

This did not work as expected, because the first frame of each video treated this way is simply not shown. Each video is only displayed from the second frame, which is a shame for single-frame videos (using the GPU's hardware encoder for lightning-fast image compression only).

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

For inspection, I now reencode the input video twice: once directly to FLV output

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

一次访问H.264,然后将其推送到FLV中.

and once to H.264, then shoving it into an FLV afterwards.

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单元不同,我怀疑这是行为不同的原因.

The first video plays fine, the second does not. The resulting FLV of the direct approach (A.flv, see below) has a slightly different file structure, especially the NAL unit differs, which I suspect is the reason for the different behavior.

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

So, my question is: If I already have a H.264 video and only want it to be copied into an FLV container without being transcoded, but the file and frame headers should be filled in correctly as is done when actually transcoding, how do I tell this to FFMPEG? Are there commands for this, such as "-c copy butGenerateValidHeader"?

以下是文件的相关部分:

Here the relevant portions of the files:

直接接触

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

A.flv

46 4C 56 01 01 00 00 00 09 00 00 00 00 12 00 00 // FLV header + metadata
B8 00 00 00 00 00 00 00 02 00 0A 6F 6E 4D 65 74
61 44 61 74 61 08 00 00 00 08 00 08 64 75 72 61
74 69 6F 6E 00 3F A0 E5 60 41 89 37 4C 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 40 9E
84 80 00 00 00 00 00 09 66 72 61 6D 65 72 61 74
65 00 40 3E 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 5C B0 00 00 00 00 00 00 09

00 00 00 C3 09 00 00 2B 00 00 00 00 00 00 00 17 // AVC sequence start
00 00 00 00
            01 4D 40 20 FF E1 00 17             // ?
                                    67 4D 40 20 // Sequence parameter set
95 A0 13 81 F7 EB 01 10 00 00 3E 80 00 0E A6 08
F1 C3 2A
         01 00 04                               // ?
                  68 EE 3C 80                   // Picture parameter set
                              00 00 00 36 09 01 // AVC NALU
94 9A 00 00 00 00 00 00 00 17 01 00 00 00
                                          00 01 // ?
94 91
      65                                        // IDR frame
        [B8 04 1D FF ...]
00 01 94 A5 09 00 00 05 00 00 00 00 00 00 00    // ?
                                             17 // AVC sequence end
02 00 00 00 00 00 00 10

先编码

ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f h264 "reencode.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

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

更新08.08.2017:添加了用于检查的输入和输出文件

Update 08.08.2017: Added input and output files for examination

  • input.h264
  • ffmpeg -f h264 -i "input.h264" -c copy "copy.flv"
  • ffmpeg -f h264 -i "input.h264" -c:v h264_nvenc -f flv "A.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"
  • ffmpeg -f h264 -i "reencode.h264" -c copy -bsf:v extract_extradata -f flv "extradata.flv"

推荐答案

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

First of all your description of file structure contradicts to real structure in your binary A.flv and B.flv (they are backward). So which result do you really want? Like A.flv with start codes: 00 00 00 01 67 .. 00 00 00 01 68 .. 00 00 00 01 65 or like B.flv with avcC + 00 17 67 .. 00 04 68 .. 00 01 94 91 65?

FLV的标准格式类似于带有avcC的B.flv(无起始代码),默认情况下使用以下格式生成:ffmpeg -i "reencode.h264" -c copy "C.flv":这是产生的 C.flv .

Standard format for FLV is like B.flv with avcC (without start codes) and it is produced by default with: ffmpeg -i "reencode.h264" -c copy "C.flv": here is resulting C.flv.

如果此文件对您有用,则尝试更新ffmpeg(我使用了master分支的自编译版本).至于带有起始代码的格式,我不知道如何产生它们.

If this file works for you than try to update your ffmpeg (I used self compiled version from master branch). As for format with start codes than I am dunno how to produce them.

这篇关于如何使用FFMPEG将H264正确包装到FLV中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆