请选择 进入手机版 | 继续访问电脑版

12360技术网 - 专业IT技术发表平台

 立即注册  找回密码
查看: 3097|回复: 3

Python实现FLV视频拼接

[复制链接]

20

主题

27

帖子

217

积分

中级会员

Rank: 3Rank: 3

积分
217
发表于 2020-1-27 03:30:45 | 显示全部楼层 |阅读模式
文章摘要

本文简单说明了FLV文件的格式,以此为出发点,使用 Python 实现FLV视频拼接
一.FLV文件格式

关于FLV文件格式的解析网上有诸多文章,在这里就简单介绍一下需要了解的部分,以便读者更好地明白各段代码的功能。
FLV文件是由文件头(Header)和文件体(Body)按顺序拼接而成。审查FLV内容时,以二进制方式读取内容。
Header:文件头表明了文件的封装格式为FLV,存储对象为音频、视频或两者。
以下为FLV文件的Header,共 9 个字节:
  1. 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 的部分,作为示例介绍一下:
  1. 头部: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. 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. 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. import timesince = time.time()flvs = ['m1.flv', 'm2.flv', 'm3.flv', 'm4.flv'] # 视频大小:45MB,20MB,59MB,54MBtarget = '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 Tag 里的参数作调整,拼接后的视频依然能够正常播放。
不过,拼接的视频是有不少隐形问题,如到视频末尾可能会出现音画不同步( 0.5 秒左右)的现象,以及不能够方便地分离出完整的视频和音频。
相关链接:使用Python解析FLV文件的Scripts Tag
如果我的文章对您有帮助,还请您点个赞,谢谢!
                                                                                                                                       
                                                    
  • 点赞                        1                        
  • 收藏                        
  • 分享                                                                                                                        
  •                                                         
                                      
    • 文章举报                           
                                                
                                                                        
                                            
                                                        Okery                                                                发布了2 篇原创文章 · 获赞 2 · 访问量 2764                                                                                            私信                                                            关注
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x




上一篇:HDR案例分析
下一篇:Delphi D10.3 LayoutsPro 控件简介 -避免输入焦点被虚拟键盘遮挡
回复

使用道具 举报

0

主题

19

帖子

409

积分

中级会员

Rank: 3Rank: 3

积分
409
发表于 2020-2-5 18:39:01 | 显示全部楼层
既然你诚信诚意的推荐了,那我就勉为其难的看看吧![www.12360.co]
回复

使用道具 举报

0

主题

17

帖子

367

积分

中级会员

Rank: 3Rank: 3

积分
367
发表于 2020-2-11 00:41:55 | 显示全部楼层
楼主发贴辛苦了,谢谢楼主分享![www.12360.co]
回复

使用道具 举报

0

主题

20

帖子

430

积分

中级会员

Rank: 3Rank: 3

积分
430
发表于 2020-2-19 15:11:32 | 显示全部楼层
这个帖子不回对不起自己![www.12360.co]
回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

12360技术网

GMT+8, 2020-2-29 13:49 , Processed in 0.085958 second(s), 26 queries .

本网站内容收集于互联网,Www.12360.Co不承担任何由于内容的合法性及健康性所引起的争议和法律责任。 欢迎大家对网站内容侵犯版权等不合法和不健康行为进行监督和举报。

© 2019-2020 Www.12360.Co

快速回复 返回顶部 返回列表