gpt4 book ai didi

ffmpeg - 如何用FFMPEG正确将H264封装成FLV?

转载 作者:行者123 更新时间:2023-12-02 02:55:53 28 4
gpt4 key购买 nike

首先,标题中的“妥当”指的是this related question ,其中的答案并不能解决我的问题。

tl;dr:对视频进行编码和直接将其存储到 FLV 中以及分两个单独的步骤执行此操作之间存在差异。我需要单独执行,如何获得与直接执行相同的结果?

Nvidia 的硬件编码器 NVENC 生成没有容器的原始 H.264 数据,这很难在大多数视频播放器中播放。对于 Adob​​e 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

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"

重新编码.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:添加了输入和输出文件以供检查

最佳答案

(1)

"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?"

您想要混合:尝试以下命令(直接将 H.264 数据复制到 FLV 容器中)。

ffmpeg -i input.h264 -c:v copy output.flv

(2)

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...

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

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

我无法使用某些时间码倒计时的 H.264 视频重现此问题。第一帧从 00hh:00mm:00ss:00msec 开始,毫秒逐帧向上移动。使用第 (1) 点中所示的命令后,如果我使用 appendBytes 向解码器提供单帧数据 (byteArray 打包为 1 帧 FLV)。

关于ffmpeg - 如何用FFMPEG正确将H264封装成FLV?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45484607/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com