什么是m3u8文件??M3U8文件是指UTF-8編碼格式的M3U文件。
M3U文件是記錄了一個(gè)索引純文本文件淘捡,打開(kāi)它時(shí)播放軟件并不是播放它焦除,而是根據(jù)它的索引找到對(duì)應(yīng)的音視頻文件的網(wǎng)絡(luò)地址進(jìn)行在線播放作彤。
原視頻數(shù)據(jù)分割為很多個(gè)TS流,每個(gè)TS流的地址記錄在m3u8文件列表中
比如我這里有一個(gè)m3u8文件竭讳,文件內(nèi)容如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:15
#EXTINF:6.916667,
out000.ts
#EXTINF:10.416667,
out001.ts
#EXTINF:10.416667,
out002.ts
#EXTINF:1.375000,
out003.ts
#EXTINF:1.541667,
ts 文件一般怎么處理???
1 只有m3u8文件灿渴,需要下載ts文件
2 有ts文件逻杖,但因?yàn)楸患用軣o(wú)法播放闻伶,需要解碼
3 ts文件能正常播放滨攻,但太多而小,需要合并
4 本篇文章處理第1和第2條內(nèi)容诞帐,加密部分跳過(guò)停蕉。
上面我提供的ts文件中并沒(méi)有加密愕鼓,也就是沒(méi)有關(guān)鍵字key ,下載ts文件之后直接合并即可
ts文件路徑獲取
由于上面的m3u8文件中所有的ts文件都是相對(duì)地址慧起,所以需要依據(jù)上篇博客中獲取到的鏈接
{'url': 'https://videos5.jsyunbf.com/2019/02/07/iQX7y3p1dleAhIv7/playlist.m3u8', 'ext': 'dplay', 'msg': 'ok', 'playertype': None}
其中前面的部分是ts的播放地址的前綴地址
# https://videos5.jsyunbf.com/2019/02/07/iQX7y3p1dleAhIv7/out005.ts
import datetime,requests
# m3u8是本地的文件路徑
def get_ts_urls(m3u8_path,base_url):?
? ? urls = []
? ? with open(m3u8_path,"r") as file:
? ? ? ? lines = file.readlines()
? ? ? ? for line in lines:
? ? ? ? ? ? if line.endswith(".ts\n"):
? ? ? ? ? ? ? ? urls.append(base_url+line.strip("\n"))
? ? return urls
ts文件下載
所有的路徑讀取完畢之后,需要對(duì)ts文件進(jìn)行下載估灿,文件的下載辦法很多
def download(ts_urls,download_path):
? ? for i in range(len(ts_urls)):
? ? ? ? ts_url = ts_urls[i]
? ? ? ? file_name = ts_url.split("/")[-1]
? ? ? ? print("開(kāi)始下載 %s" %file_name)
? ? ? ? start = datetime.datetime.now().replace(microsecond=0)
? ? ? ? try:
? ? ? ? ? ? response = requests.get(ts_url,stream=True,verify=False)
? ? ? ? except Exception as e:
? ? ? ? ? ? print("異常請(qǐng)求:%s"%e.args)
? ? ? ? ? ? return
? ? ? ? ts_path = download_path+"/{0}.ts".format(i)
? ? ? ? with open(ts_path,"wb+") as file:
? ? ? ? ? ? for chunk in response.iter_content(chunk_size=1024):
? ? ? ? ? ? ? ? if chunk:
? ? ? ? ? ? ? ? ? ? file.write(chunk)
? ? ? ? end = datetime.datetime.now().replace(microsecond=0)
? ? ? ? print("耗時(shí):%s"%(end-start))
下載過(guò)程顯示甲捏,表示下載成功,剩下的就是拼網(wǎng)速的時(shí)候了大溜。
下載完畢,是一大堆ts文件付材,記住,只要一個(gè)可以看厌衔,就可以合并了
合并ts文件? ? ?使用copy命令?如果不清楚锣夹,就去百度即可
在windows系統(tǒng)下面页徐,直接可以使用:copy/b *.ts video.mp4? 把所有ts文件合成一個(gè)mp4格式文件
copy/b D:\newpython\doutu\sao\ts_files\*.ts d:\fnew.ts
代碼合并
import os
from os import path
def file_walker(path):
? ? file_list = []
? ? for root, dirs, files in os.walk(path): # 生成器
? ? ? ? for fn in files:
? ? ? ? ? ? p = str(root+'/'+fn)
? ? ? ? ? ? file_list.append(p)
? ? print(file_list)
? ? return file_list
def combine(ts_path, combine_path, file_name):
? ? file_list = file_walker(ts_path)
? ? file_path = combine_path + file_name + '.ts'
? ? with open(file_path, 'wb+') as fw:
? ? ? ? for i in range(len(file_list)):
? ? ? ? ? ? fw.write(open(file_list[i], 'rb').read())
if __name__ == '__main__':
? ? #urls = get_ts_urls("playlist.m3u8","https://videos5.jsyunbf.com/2019/02/07/iQX7y3p1dleAhIv7/")
? ? #download(urls,"./tsfiles")
? ? combine("./ts_files","d:/ts","haha")
最終合并之后,形成一個(gè)ts文件贴唇,當(dāng)然你還可以用軟件把視頻轉(zhuǎn)換成mp4格式
也可以利用FFMPEG可以直接實(shí)現(xiàn)m3u8 轉(zhuǎn)MP4
備注部分
m3u8文件中的 m3u8標(biāo)簽與屬性說(shuō)明
#EXTM3U
每個(gè)M3U文件第一行必須是這個(gè)tag,請(qǐng)標(biāo)示作用
#EXT-X-VERSION:3
該屬性可以沒(méi)有
#EXT-X-MEDIA-SEQUENCE:140651513
每一個(gè)media URI在PlayList中只有唯一的序號(hào)豌熄,相鄰之間序號(hào)+1,
一個(gè)media URI并不是必須要包含的蹄皱,如果沒(méi)有,默認(rèn)為0
#EXT-X-TARGETDURATION
指定最大的媒體段時(shí)間長(zhǎng)(秒)。所以#EXTINF中指定的時(shí)間長(zhǎng)度必須小于或是等于這
個(gè)最大值署拟。這個(gè)tag在整個(gè)PlayList文件中只能出現(xiàn)一 次(在嵌套的情況下歌豺,一般有
真正ts url的m3u8才會(huì)出現(xiàn)該tag)
#EXT-X-PLAYLIST-TYPE
提供關(guān)于PlayList的可變性的信息,這個(gè)對(duì)整個(gè)PlayList文件有效区宇,是可選的,格式
如下:#EXT-X-PLAYLIST-TYPE::如果是VOD议谷,則服務(wù)器不能改變PlayList 文件述寡;
如果是EVENT,則服務(wù)器不能改變或是刪除PlayList文件中的任何部分,但是可以向該
文件中增加新的一行內(nèi)容掸屡。
#EXTINF
duration指定每個(gè)媒體段(ts)的持續(xù)時(shí)間(秒),僅對(duì)其后面的URI有效,title是
下載資源的url
#EXT-X-KEY
表示怎么對(duì)media segments進(jìn)行解碼碗淌。其作用范圍是下次該tag出現(xiàn)前的所有media
URI,屬性為NONE 或者 AES-128纳像。NONE表示 URI以及IV(Initialization
Vector)屬性必須不存在憔购, AES-128(Advanced EncryptionStandard)表示URI
必須存在,IV可以不存在山卦。
#EXT-X-PROGRAM-DATE-TIME
將一個(gè)絕對(duì)時(shí)間或是日期和一個(gè)媒體段中的第一個(gè)sample相關(guān)聯(lián)肮雨,只對(duì)下一個(gè)meida
URI有效,格式如#EXT-X-PROGRAM-DATE-TIME:
For example: #EXT-X-PROGRAM-DATETIME:2010-02-19T14:54:23.031+08:00
#EXT-X-ALLOW-CACHE
是否允許做cache箱玷,這個(gè)可以在PlayList文件中任意地方出現(xiàn)怨规,并且最多出現(xiàn)一次,作
用效果是所有的媒體段锡足。格式如下:#EXT-X-ALLOW-CACHE:
#EXT-X-ENDLIST
表示PlayList的末尾了波丰,它可以在PlayList中任意位置出現(xiàn),但是只能出現(xiàn)一個(gè)舶得,格
式如下:#EXT-X-ENDLIST