写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除!
文章目录
- 前言
- TS与MP4格式概述
- TS与MP4格式概述
- TS合成MP4的需求背景
- TS合成MP4的方法概述
- 合并方法
- M3U8和TS基本知识
- M3U8文件的作用
- TS文件的作用
- M3U8与TS的协作关系
- Python代码
- 必要性
- 环境依赖
- 合并代码
- 总结
- 致谢
- 参考
前言
在现代视频处理中,TS(Transport Stream)和MP4是两种常见的视频封装格式。TS格式通常用于实时传输的视频流,如通过HLS(HTTP Live Streaming)协议进行直播或点播的视频内容,而MP4则以其广泛的兼容性和高效的数据压缩技术,在存储和分享视频内容方面占据主导地位。因此,将TS文件合成MP4格式成为了一个常见的需求,特别是在需要将流媒体视频内容保存或分享到多种设备上时。
TS与MP4格式概述
TS与MP4格式概述
TS格式:
支持多节目复用和多种数据类型(如视频、音频、字幕等)的传输。TS格式通常用于流媒体传输,因为它能够高效地处理数据包的丢失和错误,保证视频流的连续性和稳定性。MP4格式:
兼容性非常好的视频格式,几乎所有的媒体设备都支持MP4格式。MP4格式采用了先进的编码技术和合理的参数设置,能够在较低的码率下提供高质量的视频和音频体验。
TS合成MP4的需求背景
设备兼容性:
MP4格式因其广泛的兼容性,能够在多种设备上无缝播放,包括智能手机、平板电脑、电视等。将TS文件合成MP4格式,可以确保视频内容能够在更多的设备上被观看和分享。存储效率:
MP4格式采用了高效的数据压缩技术,能够在保持视频质量的同时,减少文件大小,节省存储空间。对于需要长期保存或大量存储的视频内容,MP4格式是一个更好的选择。编辑和分享:
MP4格式支持多种视频和音频编码标准,便于进行视频编辑和处理。同时也是社交媒体和视频分享平台上最常用的格式之一,将TS文件合成MP4格式可以方便地进行视频分享和传播。
TS合成MP4的方法概述
使用视频格式转换工具:
如金舟视频格式转换器、MiniToolVideo Converter、LeawoVideo Converter等工具,可以快速且高质量地将TS文件合并转换成MP4格式,部分为付费功能。网上也不乏很多类似工具,甚至很多都没有专门官网,虽然支持批量转换、视频剪辑、参数设置等功能,但是很可能被种植病毒或者捆绑安装。基于FFmpeg的转换:
FFmpeg是一个强大的开源视频处理工具,支持多种视频和音频格式的转换。通过编写FFmpeg命令行或使用相关的编程接口,可以实现TS到MP4的转换,并可以对视频和音频参数进行精细控制,效果很好,但是需要编程基础,同时会涉及到环境变量的修改,对于新手不太友好。基于编程语言:
window的bat、Java、python等均能实现,目前来说python可以说是上手最简单,谁都会点深度学习。
本文主要以python为主进行说明如何将ts文件合并为MP4。
合并方法
M3U8和TS基本知识
M3U8和TS在视频流媒体传输中存在着密切的关系,它们通常一起使用,特别是在HLS(HTTP Live Streaming)协议中。
M3U8文件的作用
索引文件:
M3U8文件本质上是一个索引文件,如下图。不直接存储视频数据,而是记录了TS媒体文件的路径和播放顺序。TS文件包含实际的音视频数据。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="https://v.com/key.key",IV=0x0000000000000000
#EXTINF:2.000000,
https://v.xxxx.com/hls/0.ts
#EXTINF:2.000000,
https://v.xxxx.com/hls/1.ts
#EXT-X-ENDLIST
文件内容的解释:
EXTM3U:M3U播放列表文件的头部,表明这是一个扩展的M3U(M3U8)文件,用于HLS流媒体。
EXT-X-VERSION:3:指定HLS的版本号为3。由于不是所有的客户端或服务器都支持最新的HLS版本,需要考虑到兼容性问题。
EXT-X-TARGETDURATION:2:指定每个媒体段(segment)的最大时长为2秒。这是播放列表中最长的媒体段时长,用于客户端缓冲和播放策略。
EXT-X-MEDIA-SEQUENCE:0:设置媒体序列号的起始值为0。每个媒体段都有一个唯一的序列号,从0开始递增。
EXT-X-PLAYLIST-TYPE:VOD:指定播放列表的类型为VOD(Video On Demand),即点播内容。与之对应的是LIVE类型,表示直播内容。
EXT-X-KEY:METHOD=AES-128,URI="https://v.com/key.key",IV=0x0000000000000000:定义了用于解密媒体段的加密信息,使用的是AES-128加密方法,加密密钥可以从指定的URI获取,初始化向量(IV)固定为0x0000000000000000。客户端需要使用这个密钥和IV来解密接收到的媒体段,本字段不一定需要。
EXTINF:2.000000,:后面紧跟着的是媒体段的URL,2.000000表示该媒体段的时长为2秒。
EXT-X-ENDLIST:表示播放列表的结束。对于VOD类型的播放列表,表示所有的媒体段都已经列出,播放到此处结束。
AES-128算法
是基于AES(Advanced Encryption Standard,高级加密标准)的一种加密方式,是一种对称加密
算法,即加密和解密使用相同的密钥。AES算法支持三种密钥长度:128位、192位和256位,AES-128指的是使用128位密钥长度的AES算法。- AES-128算法以其
高效、安全且易于实现
的特点,广泛应用于各种需要保护数据安全性的场景中。它被认为是最强的加密标准之一,对各种攻击,尤其是暴力攻击的抵抗力很强,使其成为保护敏感信息的理想选择。此外,AES-128算法针对硬件和软件进行了优化,确保快速的加密和解密速度,非常适合实时应用。- AES-128算法-百度百科
UTF-8编码:
M3U8文件使用UTF-8编码格式,具有良好的跨平台兼容性。HLS协议基础:
M3U8文件是HLS协议的重要组成部分,通过将整个流媒体分成一系列小的基于HTTP的文件来下载和播放,从而实现了流媒体内容的实时传输和自适应码率流。
TS文件的作用
传输流文件:
TS(Transport Stream)文件是一种封装格式,主要用于数字广播系统,如DVB、ATSC和IPTV。TS文件包含了音视频数据,并将其封装在固定大小的数据包中,每个数据包大小为188字节。数据包结构:
TS文件的数据包结构包括TS头、适应性字段和负载。其中,TS头包含了数据包的基本信息,如同步字节、PID(Packet Identifier)等;适应性字段用于给不足188字节的数据做填充或添加其他信息;负载则包含了实际的音视频数据。无缝拼接:
两个TS片段可以无缝拼接,使得播放器能够连续播放这些片段,而不会出现破音或画面间断的情况。允许客户端从多个不同的备用源中以不同的速率下载同样的资源,从而适应不同的网络带宽条件。
M3U8与TS的协作关系
索引与数据:
在HLS协议中,M3U8文件作为索引文件,记录了TS媒体文件的路径和播放顺序。播放器通过解析M3U8文件,找到对应的TS文件并进行播放。索引与数据分离,使得HLS协议具有很高的灵活性和可扩展性。自适应码率流:
HLS协议通过提供不同码率的TS文件,允许客户端根据当前的网络带宽条件选择合适的码率进行播放。M3U8文件在这里起到了关键作用,因为它包含了不同码率TS文件的路径和相关信息。流畅播放:
M3U8文件提供了TS文件的播放顺序和路径信息,使得HLS协议能够实现流畅的视频播放体验。即使在网络状况不稳定的情况下,客户端也可以通过切换不同码率的TS文件来保证视频的连续播放。
Python代码
必要性
或许你觉得没必要使用代码,可能使用部分浏览器提供的u3m8转mp4功能就行,如基于腾讯云的某Q浏览器:
但是存在一些问题,如./andriod/data
文件被限制访问,但是实际缓存的内容在其中,上述的浏览器无法识别到相关的内容。
当然,某些方式可以解除限制,如解除MIUI对data的访问限制,但是解除数据访问限制时如何只允许信任的应用访问敏感数据,以规避安全风险或隐私泄露。个人认为出于安全的考量,不建议这么操作。
同时还有一个需要注意,对于缓存流媒体,u3m8文件#EXTINF
后面是实际的ts保存路径,一旦改变ts路径,m3u8文件的索引功能将会失效,除非将其同步修改。
因此使用代码前,需要将ts文件复制到可访问的位置,再运行下列代码。
环境依赖
脚本依赖库:
pycryptodome
tqdm
安装依赖(如果需要):
pip install tqdm
pip install pycryptodome
或(临时更换为清华源)pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tqdm
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pycryptodome
如需使用Anaconda 创建虚拟环境并配置镜像源,可参考【Anaconda 的安装、简单使用及常见的错误解决】。
最后,请确保在运行此脚本之前,确保安装了所有必要的依赖项。
合并代码
import os
from Crypto.Cipher import AES
from tqdm import tqdm
def merge_ts(path, name):
file_names = os.listdir(path) # 获取ts 源目录path下所有文件的文件名,ts文件、密钥(如果有)、其他
file_names = sorted(file_names, key=lambda x: int(str(x).split('.')[0])) # 按照升序排列,避免乱序
# 新建名为name的文件,将所读取到ts文件全部写入到这个文件中,可能需要解密
with open(f'./videos/{name}.mp4', 'ab') as des: # 可通过更改name的后缀来更改合成后的文件类型
key = None # 默认无需解密
for index, ts in enumerate(tqdm(file_names)):
# 先检查当前文件是不是ts文件
file_suffix = ts.split('.')[1]
if file_suffix != 'ts': # 若不是ts文件,进一步确认是否为密钥,两者均不参与后续的视频保存
if file_suffix == 'key': # 若为key文件,读取并赋值给key
with open(os.path.join(path, ts), "rb") as fkey:
key = fkey.read()
continue
if key is not None: #如需解密,默认AES-128,读取视频后保存
aes = AES.new(key, AES.MODE_CBC, b'0000000000000000')
with open(os.path.join(path, ts), "rb") as tmp:
try:
des.write(aes.decrypt(tmp.read()))
except Exception as e:
print(e)
else:
with open(os.path.join(path,ts), "rb") as tmp:
try:
des.write(tmp.read()) # 将当前ts文件以追加写入到名为name的文件
except Exception as e:
print(e)
if __name__ == '__main__':
root_path = os.getcwd()
path = os.path.join(root_path,'tss')
name = 'ff'
merge_ts(path,name)
注意事项:
- 文件排序:ts文件名升序排列,这是由
EXT-X-MEDIA-SEQUENCE:0
决定的,避免1,10,11之类的排序。
脚本处理了非.ts文件,特别是检查并读取了.key文件(如果存在)以获取解密密钥。 - 解密处理:使用pycryptodome库中的AES类来进行解密,默认ts同级目录下有名为
number.key
的密钥文件,IV(初始化向量)可由M3U8文件中得到,此处使用的硬编码,并默认所有.ts文件都需要使用相同的密钥进行解密。若IV是随机的,并且与密文一起存储或传输,需要联合读取。 - 进度可视化:使用tqdm库来显示进度条,有助于了解合并过程的进度,但ts数量较少时候没有必要使用。
- 上下文管理器:with 方式打开文件,可避免人为忽略关闭文件的问题,同时需要打开文件的方式,是否需要追加。
总结
总结: 本文介绍了一种使用Python脚本将TS文件合并为MP4的方法,主要解决流媒体视频内容的保存和分享问题。脚本通过排序、解密(如AES-128)和合并TS文件,最终生成一个MP4文件。过程中,使用了pycryptodome库进行解密,tqdm库实现进度可视化。此方法相比直接使用浏览器或第三方工具,具有更高的灵活性和安全性,特别是在处理加密TS文件和需要自定义输出路径时。同时,脚本考虑了非TS文件的处理,如自动读取和解密密钥文件,增加了实用性。
致谢
欲尽善本文,因所视短浅,怎奈所书皆是瞽言蒭议。行文至此,诚向予助与余者致以谢意。
参考
[1] https://baike.baidu.com/item/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86/468774