使用python+FFmpeg實現m3u8文件內的ts視頻 解密、合並 && ffmpeg截取視頻


m3u8文件內內容

 

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:12
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.key",IV=0x00000000000000000000000000000001
#EXTINF:11,
00154.ts  //ts視頻的路徑一般都是絕對路徑,我這里沒有給出絕對鏈接
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.key",IV=0x0000000000000000000000000000009B
#EXTINF:10,
00155.ts
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.key",IV=0x0000000000000000000000000000009C
#EXTINF:11,
00156.ts
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.key",IV=0x0000000000000000000000000000009D
#EXTINF:10,
00157.ts

 

這個是正式的m3u8文件(參看:https://blog.csdn.net/weixin_41624645/article/details/95939510):

 

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0

//這里是注釋,真實文件里不會有的,
//看看你的m3u8文件里有沒有這一行,如果有的話,那么恭喜你這個m3u8文件是加密的,請繼續往下看
//如果沒有這行的話,特別是沒有這個#EXT-X-KEY,那么同樣恭喜你,這個m3u8沒有加密,你直接百度vlc下載合並就行,也可根據本文章進行合並
#EXT-X-KEY:METHOD=AES-128,URI="http://www.example.com/20180125/key.key"


#EXTINF:12.5,
//下面的這個其實才是視頻真正的地址,你放在瀏覽器地址欄上直接回車是可以直接下載的
//不過這樣的鏈接在m3u8文件里會有很多,建議使用工具下載(迅雷)、ffmpeg、vlc等
//這里還可能出現GBDYO3576000.ts這種情況,其實是把前面的路徑省略了,可根據m3u8文件的路徑自行加上
http://www.example.com/20180125/GBDYO3576000.ts
#EXTINF:12.5,
http://www.example.com/20180125/GBDYO3576001.ts
#EXTINF:12.5,
http://www.example.com/20180125/GBDYO3576002.ts

 

 

 

上面這個m3u8文件中有這樣的字段:

 

#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.key",IV=0x00000000000000000000000000000001

 

就證明你這個m3u8內的ts視頻是加密的(意思就是你可以把m3u8內的ts視頻下載,但是因為視頻被加密導致播放器無法播放)

 

那么我們就需要對ts視頻解密,看上面那個字段的URI的值

 

URI="E:/CTF/test/key.key"

 

 

它的意思就是ts視頻的解密文件鏈接為:

E:/CTF/test/key.key

那我們就把它下載下來。可能這個鏈接不是絕對路徑,那你就去找一下這個網站的路徑,把這個相對路徑加到后面就組成了key.key文件的絕對路徑

 

下載之后這個時候你就有兩個文件一個是后綴為m3u8文件,里面放置ts視頻絕對路徑。還有一個key.key文件,放置視頻解密所需東西

這個時候你把后綴為m3u8的文件名改為:index.m3u8

這個時候你把key.key的文件名改為:key.m3u8

 

我們假設你已經把m3u8文件內的所有ts視頻都下載下來了,且ts視頻地址和index.m3u8和key.m3u8文件在同一目錄下

 

這個時候我們要修改一下m3u8文件內容:

 

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:12
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD    //注意改一下這個URI地址為你電腦上的key.m3u8文件路徑,相對路徑也行
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.m3u8",IV=0x00000000000000000000000000000001
#EXTINF:11,
00154.ts  //注意因為我的ts視頻和index.m3u8文件在同一目錄下,所以我直接寫出ts視頻文件名就行,如果你的視頻和index文件不再一個地方,你給出你本地的絕對地址也行
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.m3u8",IV=0x0000000000000000000000000000009B
#EXTINF:10,
00155.ts
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.m3u8",IV=0x0000000000000000000000000000009C
#EXTINF:11,
00156.ts
#EXT-X-KEY:METHOD=AES-128,URI="E:/CTF/test/key.m3u8",IV=0x0000000000000000000000000000009D
#EXTINF:10,
00157.ts

 

 

 

接下來還需要下載一款工具ffmpeg,下載Static的那個版本就可以,然后配置環境變量Path,在Path后面直接添加你ffmpeg的安裝目錄加上/bin就可以了,安裝完成之后重啟一下,重啟之后打開你index.m3u8所在的文件執行下面命令:

 

ffmpeg -allowed_extensions ALL -i index.m3u8 -c copy out.mp4

 

報錯了可執行:

 

ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,crypto,tcp" -i index.m3u8 -c copy out.mp4

 

如果這里報錯了,那么打開你的index.m3u8文件,修改URI的路徑為網絡路徑(你下載時的路徑),然后執行

 

ffmpeg -protocol_whitelist "file,http,crypto,tcp" -i index.m3u8 -c copy out.ts

 

 

 

操作之后合並的視頻就是out.ts

所有index.m3u8的ts視頻都是從00001.ts開始,因為我下載那個總的視頻比較大,所以index.m3u8內的ts小視頻鏈接三百多個,所以我就挑出來了幾個ts鏈接

然后下載了。這個時候你要注意了,因為你只下載了幾個ts視頻,那也就證明index.m3u8內的有些ts視頻你的電腦本地沒有,那么你就要在index.m3u8文件內把這些不存在的刪掉,要不然執行ffmpeg命令會報錯:

[crypto @ 000000000054de40] Unable to open resource: D:\temp\vd201906291\O7rSBp5
l5847008.ts
[hls,applehttp @ 0000000000532c40] Failed to open segment 8 of playlist 0
[hls,applehttp @ 0000000000532c40] Error when loading first segment ‘D:\temp\vd2
01906291\O7rSBp5l5847000.ts’
D:\temp\vd201906291\tsmaster.m3u8: Invalid data found when processing input

最主要的原因就是因為m3u8中本地文件的路徑寫錯了啦,所以會提示無效數據。正確的路徑寫法見上一篇文章。如果還是這個提示,就請檢查一下這些文件是不是都存在啦。

 

 

因為有的index.m3u8文件內ts視頻很多,我們手動下載要累死,那么我們可以使用python通過多線程來加速下載

使用下面這個代碼,你需要在python文件同目錄下提供一個index.m3u8文件就可以了

代碼就會根據index.m3u8內的ts視頻絕對鏈接,進行下載

 

import requests,os,threading
def getTsUrl():
    ts_url_list = []
    # baseUrl = "https://ycalvod.yicai.com/record/live"
    with open("qwe.m3u8", "r", encoding="utf-8") as f:
        m3u8Contents = f.readlines()
        for content in m3u8Contents:
            if content.endswith("ts\n"):
                ts_Url = content.replace("\n", "").replace("..", "")
                ts_url_list.append(ts_Url)
                # print(ts_Url)
    return ts_url_list

def download_ts_video(download_path, ts_url_list,start,last):
    # download_path = r"C:\Users\Administrator\Desktop\AiShu\下載視頻\TS視頻"
    for i in range(start,last):
        ts_url = ts_url_list[i]
        try:
            response = requests.get(ts_url, stream=True, verify=False)
        except Exception as e:
            print("異常請求:%s" % e.args)
            return
        name = ts_url.split('_')[-1].strip()  # 截取ts鏈接的最后一部分,結果為00001.ts
        ts_path = download_path + "\{}".format(name)
        with open(ts_path, "wb+") as file:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    file.write(chunk)

def main(total,block,total_vedio): # 啟動多線程
    start = 0
    thread_list = []  # 線程存放列表
    for i in range(total):
        if start + block > total_vedio:
            t = threading.Thread(target=download_ts_video, args=(download_path,ts_url_list ,start, total_vedio,))
        else:
            t = threading.Thread(target=download_ts_video, args=(download_path,ts_url_list,start , start + block,))
            start += block
        t.setDaemon(True)
        thread_list.append(t)

    for t in thread_list:
        t.start()

    for t in thread_list:
        t.join()


if __name__ == '__main__':
    download_path = r"E:/CTF/test"  # 視頻保存在本地的地址
    total = 20  # 線程總數
    ts_url_list = getTsUrl() # 獲取所有ts鏈接
    block = int(len(ts_url_list) / total) # 一共有total個線程,那么平均給每一個線程多少個下載任務
    if len(ts_url_list) % total != 0:
        block += 1
    main(total,block,len(ts_url_list))
    # download_ts_video(download_path, ts_url_list)
    # print(ts_url_list)

 

 

因為最后index.m3u8文件內的鏈接都要改成本地鏈接,一個一個改起來太慢,我使用的是notepad++,這個軟件有個工具替換,可以一次改完

 ts鏈接的前面基本上都一樣,你可以把ts視頻絕對鏈接前面一部分選中,把它替換為空,那么文件名就是00001、00002、00003......類型的了

 

 

運行結果:

 

這是個警告,如果你想處理的話,你可以在請求代碼前添加如下代碼即可:

 

如果想要截圖視頻,可以通過以下命令(參考鏈接為:https://blog.csdn.net/huangxingli/article/details/46663143):

ffmpeg  -i ./plutopr.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:00:15 ./cutout1.mp4 -y

 

-ss time_off        set the start time offset 設置從視頻的哪個時間點開始截取,上文從視頻的第10s開始截取
-to 截到視頻的哪個時間點結束。上文到視頻的第15s結束。截出的視頻共5s.
如果用-t 表示截取多長的時間如 上文-to 換位-t則是截取從視頻的第10s開始,截取15s時長的視頻。即截出來的視頻共15s.
 
注意的地方是:
 如果將-ss放在-i ./plutopr.mp4后面則-to的作用就沒了,跟-t一樣的效果了,變成了截取多長視頻。一定要注意-ss的位置。
 
參數解析
-vcodec copy表示使用跟原視頻一樣的視頻編解碼器。
-acodec copy表示使用跟原視頻一樣的音頻編解碼器。
 
-i 表示源視頻文件
-y 表示如果輸出文件已存在則覆蓋。

 

合並視頻:先弄一個filelist.txt文件

 

file  'D:\delphisr\騰訊下載地址解析子串\k0028qzpkdl.321002.1.ts'
file  'D:\delphisr\騰訊下載地址解析子串\k0028qzpkdl.321002.2.ts'
file  'D:\delphisr\騰訊下載地址解析子串\k0028qzpkdl.321002.3.ts'
file  'D:\delphisr\騰訊下載地址解析子串\k0028qzpkdl.321002.4.ts'

 

 

 

然后進入這個目錄執行下面這個命令:

 

ffmpeg -f concat -safe 0 -i filelist.txt -c copy out.mp4

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM