- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python实现FLV视频拼接功能由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
文章摘要 。
本文简单说明了FLV文件的格式,以此为出发点,使用 Python 实现FLV视频的拼接.
一.FLV文件格式 。
关于FLV文件格式的解析网上有诸多文章,在这里就简单介绍一下需要了解的部分,以便读者更好地明白各段代码的功能.
FLV文件是由文件头(Header)和文件体(Body)按顺序拼接而成。审查FLV内容时,以二进制方式读取内容.
Header:文件头表明了文件的封装格式为FLV,存储对象为音频、视频或两者。 以下为FLV文件的Header,共 9 个字节:
b'FLV\x01\x05\x00\x00\x00\t' 前 3 个字节(FLV)说明这是一个FLV文件 第 4 个字节(\x01)为版本号,固定为 1 第 5 个字节(\x05)表明存储对象,需将其转化成二进制(00000101)查看,左、右边的 1 分别表示文件含有音频和视频 后 4 个字节(\x00\x00\x00\t)表示文件头的长度,其值固定为 9 。
Body:文件体由若干个 Tag 组成,除了第一个,每个 Tag 是由头部( 11 字节)、主体(不定长)和尾部( 4 字节)组成。第一个 Tag 只有尾部.
Tag 又分为 3 类,脚本(scripts)、音频(audio)和视频(video)。通常第 2 个 Tag 为脚本类型,且只有一个,后续的都是音视频类型.
以下为脚本 Tag 的部分,作为示例介绍一下:
头部:b'\x12\x00\tb\x00\x00\x00\x00\x00\x00\x00' 第 1 个字节(\x12)表示 Tag 类型,脚本类型的对应值为 18 ,音频为 8 ,视频为 9 第 2-4 个字节(\x00\tb)表示 Tag 主体的长度,此处为 2402 第 5-7 个字节(\x00\x00\x00)为时间戳,脚本类型的时间戳通常为 0 第 8 个字节(\x00)是时间戳的扩展,当前 3 个字节不够用时会用这个字节当作大端 后 3 个字节(\x00\x00\x00)是 Stream id,固定为 0 。
主体:脚本 Tag 的主体包含FLV视频的基本信息,如时长、大小、分辨率等,比较复杂,在此不作介绍 。
尾部:b'\x00\x00\tm' 。
固定 4 字节,表示 Tag 头部加主体的长度,即 11 + 2402 = 2413 。
二.FLV视频拼接 。
将多个FLV视频合成一个可以正常播放的视频,便足够满足大部分的需求。因此,在接下来的拼接过程中,不会对FLV进行细致入微的调整,达到基本要求即可.
设置阅读器 。
阅读器可以使我们很方便地读取文件内容.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class
Reader():
def
__init__(
self
, content):
# content (bytes):FLV文件的二进制内容
self
.content
=
content
self
.start
=
0
self
.eof
=
False
# 判断是否已读完全部内容
self
.length
=
len
(
self
.content)
def
read(
self
, n
=
1
):
# 设置 if 语句防止过度读取内容
if
self
.length > (
self
.start
+
n):
out
=
self
.content[
self
.start:
self
.start
+
n]
self
.start
+
=
n
else
:
out
=
self
.content[
self
.start:]
self
.eof
=
True
return
out
|
向新建FLV文件写入 Header 和 Tag 。
在这里假设要拼接的视频基本信息相似,即都含有音视频,分辨率、码率等相同或相近.
为了生成一个可以正常播放的FLV视频,Header 和 Tag 是必不可少的。我们可以选取第一个FLV的文件头写入新建FLV中,然后依次将修改过时间戳的 Tag 写入其中,便可达到拼接目的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
def
add_flv(flv, target, videoTimeStamp, audioTimeStamp):
# 修改并添加 Tag 的函数
with
open
(flv,
'rb'
) as f:
content
=
f.read()
reader
=
Reader(content)
header
=
reader.read(
13
)
with
open
(target,
'ab'
) as f:
while
not
reader.eof:
# 一直读取直到读完,此时 reader.eof = True
dataType
=
reader.read(
1
)
dataSize
=
reader.read(
3
)
timeStamp
=
int
.from_bytes(reader.read(
3
),
'big'
)
# 将 3 字节转换成整数
headerRemained
=
reader.read(
4
)
if
dataType
=
=
b
'\t'
:
# 视频
timeStamp
+
=
videoTimeStamp
videoTS
=
timeStamp
if
dataType
=
=
b
'\x08'
:
# 音频
timeStamp
+
=
audioTimeStamp
audioTS
=
timeStamp
timeStamp
=
timeStamp.to_bytes(
3
,
'big'
)
# 将整数转换成 3 字节
tagHeader
=
dataType
+
dataSize
+
timeStamp
+
headerRemained
tagData_andSize
=
reader.read(
int
.from_bytes(dataSize,
'big'
)
+
4
)
f.write(tagHeader)
f.write(tagData_andSize)
return
videoTS, audioTS
def
merge_flv(flvs, target):
# 主函数
videoTS
=
0
audioTS
=
0
for
i, flv
in
enumerate
(flvs):
with
open
(flv,
'rb'
) as f:
content
=
f.read()
reader
=
Reader(content)
header
=
reader.read(
13
)
# flvHeader + tagSize0
if
i
=
=
0
:
# 写入第 1 个FLV视频的文件头
with
open
(target,
'wb'
) as f:
f.write(header)
videoTS, audioTS
=
add_flv(flv, target, videoTS, audioTS)
|
拼接 。
1
2
3
4
5
6
7
8
|
import
time
since
=
time.time()
flvs
=
[
'm1.flv'
,
'm2.flv'
,
'm3.flv'
,
'm4.flv'
]
# 视频大小:45MB,20MB,59MB,54MB
target
=
't.flv'
merge_flv(flvs, target)
end
=
time.time()
print
(
'Merging flvs takes {:.2f} s'
.
format
(end
-
since))
# Merging flvs takes 0.88 s
|
可以看到,拼接 4 个共 178MB视频用时 0.88 秒.
总结 。
FLV文件格式还是比较简明的,对数据的要求也是比较宽松的,即便没有对 Scripts 里的参数作调整,拼接后的视频依然能够正常播放.
不过,拼接的视频是有不少隐形问题,如到视频末尾可能会出现音画不同步( 0.5 秒左右)的现象,以及不能够方便地分离出完整的视频和音频.
以上所述是小编给大家介绍的Python实现FLV视频拼接功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢! 。
原文链接:https://blog.csdn.net/Okery/article/details/104054228 。
最后此篇关于Python实现FLV视频拼接功能的文章就讲到这里了,如果你想了解更多关于Python实现FLV视频拼接功能的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
.splice() 方法的基本问题,以及如何最好地从数组中删除元素。 我想使用 .splice() 从数组中删除一个项目,但是当我这样做时,我希望返回原始数组 减去 删除的元素。 .splice()
我正在过滤同位素库。单击按钮会添加到称为过滤器的数组中。这是正常工作的,但是当用户单击事件按钮时,我希望从数组中删除过滤的类别。由于某种原因,事实并非如此。 这是特定的代码: if($(this).h
几个月前,我将一个 Subversion 存储库转换为 Mercurial,结果在我的修订历史中留下了两个毫无意义的空白。我试图弄清楚我是否可以拼接间隙,但我一直无法让工具精确地完成我想要的。 在项目
我制作简单的射击游戏,但有一个问题(有时): GIF Game problem 3颗子弹被移除(但只有一颗子弹相撞)。子弹和敌人(蓝色方 block )位于一个数组中(var objects = []
假设我们在 JavaScript 中有两个数组,[3,4,7] 和 [5,6]。 在不排序或使用 .apply 的情况下,将 [5,6] 插入索引 2 处的 [3,4,7] 的最佳方式是什么实现结果数
我试图在从数组中删除项目时添加纸质警报对话框,但我似乎无法理解这是如何工作的。 我现在可以使用以下功能,无需对话框: _delete(e) { var index = this.t
我正在尝试使用 splice() 从 jQuery 对象中删除元素. 但是,最终发生的情况是所有其他项目都被删除。我假设这是由于使用 splice 重新索引造成的。 我要淡入每个 所以我需要从顶部开始
这是我尝试从数组中动态删除一个值的尝试 $('.btn-remove').click(function() { var players = ["compare","13076","13075"
我正在考虑在 Visual Studio 2008 上使用 OpenCV 2.3.1 实时拼接来自 2 个或更多(目前可能是 3 或 4 个)摄像头的图像。 但是,我很好奇它是如何完成的。 最近研究了
我在将两个数组拼接在一起时遇到问题。假设我有两个数组: a = array([1,2,3]) b = array([4,5,6]) 当我执行 vstack((a,b)) 时,我得到了 [[1,2,3]
我拼接 css 文件以提高性能。 现在我想包含一个 minify 函数,如下所示。我该如何合并它? function minify( $css ) { $css = preg_replace(
我有两个 matlab 向量。第一个有 N 个元素,另一个有 k*N。我知道 k 是什么,我想拼接列表,使第一个向量中的每个元素出现在下一个向量中相应的 k 元素之前。例如: k = 3 x = [1
我有以下上下文: https://jsfiddle.net/eqntaqbt/2/ obj.forEach(function(user, index){ var userName = user
假设你有一个像这样的数组: var arr= [{id:121, v:'a'}, {id:232, 'b'}]; 你需要找到 id: 232 并删除它,所以你可以这样做: for (var i = a
似乎是通过 建立报价语法非常低效。例如创建一个整数列表 let q1 = List.foldBack (fun n acc -> ) [1..100000] Real: 00:00:05.714,
我正在为一家希望为其用户创建服务的公司开发应用程序。该公司目前提供时长约为 1.5 小时的视频,他们想要集成的服务是让用户能够“录制”这个较大视频的剪辑,以创建本质上的精彩片段。此服务的最终结果将是
splice 当 OFFSET 在数组中但 LENGTH 的末尾超过数组末尾时,是否可以? 最佳答案 易于尝试。 $ perl -wE' my @a = "a".."e"; my @b =
以前从未使用过 Tkinter,我不太确定如何使用它或它是如何工作的。 Windows IDLE Shell。 import time from tkinter import * input("Pre
这里是 Javascript 新手 -- 我有以下数组: var group = ({ one: value1, two: value2, three:
我的屏幕上打印了以下行: Would you like to pay €xx to POS_ID Latte X 1....€2.50-Salad X 1....€4.00-Wrap X 1..
我是一名优秀的程序员,十分优秀!