最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用ffmpeg實現(xiàn)mp4與m3u8相互轉(zhuǎn)換

 更新時間:2025年11月18日 09:35:58   作者:普通網(wǎng)友  
FFmpeg 是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機(jī)程序,它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案,下面小編就和大家詳細(xì)介紹一下吧

FFmpeg 是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機(jī)程序。它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案。

一、MP4 轉(zhuǎn) M3U8

M3U8 是 Unicode 版本的 M3U,用 UTF-8 編碼。”M3U” 和 “M3U8” 文件都是蘋果公司使用的 HTTP Live Streaming(HLS) 協(xié)議格式的基礎(chǔ),這種協(xié)議格式可以在 iPhone 和 Macbook 等設(shè)備播放。

簡單來說,m3u8是一個視頻格式,就是將一個視頻分成很多的小部分,這樣方便視頻的加載。

1、操作簡單,但效率低

ffmpeg -i input.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 2 -hls_time 15 output.m3u8

生成的效果是:

將 input.mp4 視頻文件每 15 秒生成一個 ts 文件,最后生成一個 m3u8 文件,m3u8 文件是 ts 的索引文件。

我們直接用 VLC media player 等播放軟件是可以直接打開 m3u8 文件,像播放 mp4 一樣。

默認(rèn)的每片長度為 2 秒,m3u8 文件中默認(rèn)只保存最新的 5 條片的信息,導(dǎo)致最后播放的時候只能播最后的一小部分(直播的時候特別注意)。

  • -hls_time n 設(shè)置每片的長度,默認(rèn)值為 2,單位為秒。
  • -hls_list_size n 設(shè)置播放列表保存的最多條目,設(shè)置為 0 會保存有所片信息,默認(rèn)值為5。
  • -hls_wrap n 設(shè)置多少片之后開始覆蓋,如果設(shè)置為0則不會覆蓋,默認(rèn)值為0。這個選項能夠避免在磁盤上存儲過多的 片,而且能夠限制寫入磁盤的最多的片的數(shù)量。
  • -hls_start_number n 設(shè)置播放列表中 sequence number 的值為 number,默認(rèn)值為 0。

注意:播放列表的 sequence number 對每個 segment 來說都必須是唯一的,而且它不能和片的文件名(當(dāng)使用 wrap 選項時,文件名有可能會重復(fù)使用)混淆。

2、效率優(yōu)化版,提升效率

TS 文件是一種媒體的擴(kuò)展名,它是日本高清攝像機(jī)拍攝下進(jìn)行的封裝格式。MPEG2-TS(Transport Stream“傳輸流”;又稱TS、TP、MPEG-TS 或 M2T)是用于音效、圖像與數(shù)據(jù)的通信協(xié)定,最早應(yīng)用于DVD的實時傳送節(jié)目。MPEG2-TS格式的特點就是要求從視頻流的任一片段開始都是可以獨立解碼的。

# 1.視頻整體轉(zhuǎn)碼ts
ffmpeg -y -i music.mp4  -vcodec copy -acodec copy -vbsf h264_mp4toannexb out\music.ts
# 2. ts 文件切片
ffmpeg -i music.ts -c copy -map 0 -f segment -segment_list out\music.m3u8 -segment_time 10 out\15s_%3d.ts

3、hls_time 切片時間不準(zhǔn)確的問題

播放 m3u8 的 ts 切片,必須要完整的下載一個 ts 切片,才能夠播放,設(shè)置hls_time 的時間間隔越短越好( 根據(jù)實際情況來 ),實際過程中設(shè)置切片時間間隔為 2 秒,調(diào)用如下指令:

ffmpeg -i test.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_time 2 index.m3u8

但沒有按照參數(shù)輸入,進(jìn)行切片。

原因:

ts 文件的切割,還跟原文件視頻的 GOP 大小有關(guān)系(也就是兩個 I 幀之間的時間間隔),因為任何一個 ts 分片第一幀必須是I幀,否則無法最快播放,并且第一幀不是 I 幀,對于播放器也是沒有任何的意義,直接被播放器扔掉。任何一個視頻流必須在獲取到第一個I幀才能成功解碼出圖片。雖然指定了 1 秒切割一個 ts 文件,實際上,由于原視頻流可能好幾秒才有一個 I 幀,所以必須等到下一個 I 幀,才會重新開始切片。

解決:

既然知道要1秒產(chǎn)生一個ts分片,那就必須產(chǎn)生切片的過程中,強(qiáng)制一秒中產(chǎn)生一個關(guān)鍵幀。

設(shè)置關(guān)鍵幀間隔,設(shè)置間隔為 2 秒的參數(shù)如下:-force_key_frames "expr:gte(t,n_forced*2)“

完整指令如:

ffmpeg -i test.mp4 -force_key_frames "expr:gte(t,n_forced*2)" -strict -2 -c:a aac -c:v libx264 -hls_time 2 -f hls index.m3u8

4、m3u8 格式解析

完整的 m3u8 文件有三部分:

  • index.m3u8,保存視頻的基本信息和分段文件順序;
  • key,如果視頻加密,保存密鑰;
  • data文件,其他都是視頻的數(shù)據(jù)文件。

具體內(nèi)容解析:

    #EXTM3U,是文件開始
    #EXT-X-VERSION,標(biāo)識HLS的協(xié)議版本號;
    #EXT-X-TARGETDURATION,表示每個視頻分段最大的時長(單位秒);
    #EXT-X-MEDIA-SEQUENCE,表示播放列表第一個 URL 片段文件的序列號;
    #EXT-X-PLAYLIST-TYPE,表明流媒體類型;
    #EXT-X-KEY,加密方式,這里加密方式為AES-128,同時指定IV,在解密時需要;
    #EXTINF,表示其后 URL 指定的媒體片段時長(單位為秒)。

二、播放演示

HLS 的工作原理是把整個流分成一個個小的基于 HTTP 的文件來下載,每次只下載一些。

當(dāng)媒體流正在播放時,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應(yīng)不同的數(shù)據(jù)速率。

在開始一個流媒體會話時,客戶端會下載一個包含元數(shù)據(jù)的 extended M3U (m3u8) playlist文件,用于尋找可用的媒體流。

HLS 只請求基本的 HTTP 報文,與實時傳輸協(xié)議(RTP)不同,HLS 可以穿過任何允許 HTTP 數(shù)據(jù)通過的防火墻或者代理服務(wù)器。

它也很容易使用內(nèi)容分發(fā)網(wǎng)絡(luò)來傳輸媒體流。

三、m3u8(ts) 合并為 MP4

遠(yuǎn)程文件

ffmpeg -i “https://xushanxiang.com/demo/ffmpeg/hls265/output.m3u8” -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4

本地文件

1、打開 cmd

2、輸入指令,按照文件的實際路徑合并

合并成 ts文件 copy /b  F:\f\*.ts  E:\f\new.ts

合并成 MP4 文件 copy /b  F:\f\*.ts  E:\f\new.MP4

而通過 ffmpeg 命令如下:

直接轉(zhuǎn):

ffmpeg -i new.ts -c copy -map 0:v -map 0:a output.mp4

指定音頻流(一般用這個):

ffmpeg -i new.ts -c copy -map 0:v -map 0:a -bsf:a aac_adtstoasc output.mp4

重編碼視頻:

ffmpeg -y -i new.ts -c:v libx264 -c:a copy -bsf:a aac_adtstoasc output.mp4

php實現(xiàn)代碼

$url = 'https://******.m3u8?Expires=1585381145&OSSAccessKeyId=******&Signature=******';
 
$ts_content = file_get_contents($url);
$ts_content = explode(',', $ts_content);
$ts_file = array();
 
foreach ($ts_content as $key => $value) {
    if($key == 0) continue;
    $value = trim($value);
    $ts_file[] = substr($value, 0, strpos($value, '.ts') + 3);
}
 
$url_prefix = substr($url, 0, strpos($url, '.m3u8'));
$url_prefix = substr($url, 0, strrpos($url, '/') + 1);
$file_content = '';
 
foreach ($ts_file as $key => $value) {
    $file_content .= file_get_contents($url_prefix . $value);
}
 
file_put_contents('tmp_out.ts', $file_content);
 
// FFMPEG_PATH 是你自己解壓ffmpeg的bin路徑,例如我的是F:/ffmpeg/bin/
exec(FFMPEG_PATH . "ffmpeg -i tmp_out.ts tmp_out.mp4");

Python實現(xiàn)代碼

目錄結(jié)構(gòu)

./
  |-- m3u8.py
  |-- result
  |-- 文件1
    |-- key
    |-- index.m3u8
    |-- data...
  |-- 文件2
    |-- ...

完整代碼

import os
import sys
import time
from Crypto.Cipher import AES
 
def fileList(findex):
    rpath = os.path.dirname(os.path.realpath(findex))
    name = rpath.split("\\")[-1]
    fi = open(findex, 'r')
    flag = False
    IV = None
    tl = []
    for line in fi.readlines():
        if line.startswith("#EXT-X-KEY"):
            # 如果存在 IV 則提?。?
            if line.split(",")[-1].startswith("IV="):
                IV = line.split(",")[-1][5:]
                IV = bytes.fromhex(IV)
        if line.startswith("#EXTINF"):
            flag = not flag
            continue
        if flag:
            tmp = line.strip().split("/")[-1]
            tmp = os.path.join(rpath, tmp)
            tl.append(tmp)
            flag = not flag
    fi.close()
    fk = open(os.path.join(rpath, "key"), 'rb')
    key = fk.read()
    fk.close()
    return name, tl, key, IV
 
def aes_decode(data, key, IV):
    # 如果沒有指定 IV 值,則直接使用 key 值
    if not IV:
        IV = key
    cryptor = AES.new(key, AES.MODE_CBC, IV)
    plain_text = cryptor.decrypt(data)
    return plain_text
 
def main():
    fp = os.listdir()
    used = [s[:-4] for s in os.listdir("./result/")]
    for ind in fp:
        if not ind.isdigit():
            continue
        if ind in used:
            continue
        try: 
            name, fl, key, IV = fileList(os.path.join(ind, "index.m3u8"))
        except:
            print("-"*30)
            print("[-] Errot! file: ", ind)
            print("-"*30)
            continue
        print("[*] Begin process file: ", name)
        start = time.time()
        f = open(os.path.join("./result/", name+".mp4"), 'ab')
        for i in fl:
            with open(i, 'rb') as inf:
                data = inf.read()
                f.write(aes_decode(data, key, IV))
        f.close()
        print("[+] Sucessfully! Cost time: ", time.time()-start)
 
main()

到此這篇關(guān)于Python使用ffmpeg實現(xiàn)mp4與m3u8相互轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)ffmpeg實現(xiàn)mp4與m3u8互轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python如何刪除文件夾下的所有文件

    python如何刪除文件夾下的所有文件

    文章介紹了如何使用Python刪除文件夾下的所有文件,如果要刪除特定文件,可以使用類似的方法,作者分享了個人經(jīng)驗,并鼓勵大家支持腳本之家
    2026-01-01
  • Python中reset_index()函數(shù)的使用

    Python中reset_index()函數(shù)的使用

    本文主要介紹了Python中reset_index()函數(shù)的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 關(guān)于python selenium 運(yùn)行時彈出窗口問題

    關(guān)于python selenium 運(yùn)行時彈出窗口問題

    最近在做一個網(wǎng)頁代填項目,用到了python的selenium知識,經(jīng)過了各種嘗試與搜索最后終算是較完美的解決了,下面小編給大家?guī)砹藀ython selenium 運(yùn)行時彈出窗口問題,感興趣的朋友一起看看吧
    2021-11-11
  • 基于Python編寫一個解析器

    基于Python編寫一個解析器

    這篇文章主要給大家介紹了如何基于Python編寫一個解析器,文章通過代碼示例介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2023-08-08
  • 解決新django中的path不能使用正則表達(dá)式的問題

    解決新django中的path不能使用正則表達(dá)式的問題

    今天小編就為大家分享一篇解決新django中的path不能使用正則表達(dá)式的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • Python的賦值、深拷貝與淺拷貝的區(qū)別詳解

    Python的賦值、深拷貝與淺拷貝的區(qū)別詳解

    這篇文章主要介紹了Python的賦值、深拷貝與淺拷貝的區(qū)別,需要的朋友可以參考下
    2020-02-02
  • Python txt文件加入字典并查詢的方法

    Python txt文件加入字典并查詢的方法

    今天小編就為大家分享一篇Python txt文件加入字典并查詢的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Python list運(yùn)算操作代碼實例解析

    Python list運(yùn)算操作代碼實例解析

    這篇文章主要介紹了Python list運(yùn)算操作代碼實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • python使用雙豎線分割的實現(xiàn)

    python使用雙豎線分割的實現(xiàn)

    本文主要介紹了python使用雙豎線分割的實現(xiàn),通過接收用戶輸入的字符串,使用split()方法進(jìn)行分割,并將結(jié)果輸出給用戶,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Python中字符串轉(zhuǎn)換為列表的常用方法總結(jié)

    Python中字符串轉(zhuǎn)換為列表的常用方法總結(jié)

    本文將詳細(xì)介紹Python中將字符串轉(zhuǎn)換為列表的八種常用方法,每種方法都具有其獨特的用途和適用場景,文中的示例代碼講解詳細(xì),感興趣的可以了解下
    2023-11-11

最新評論

丁青县| 公安县| 永康市| 温泉县| 明星| 蒲城县| 镇巴县| 宁强县| 张家港市| 贡山| 邵武市| 汶川县| 庆阳市| 德保县| 霸州市| 凤庆县| 武清区| 山东省| 赤壁市| 且末县| 金昌市| 白水县| 嘉黎县| 高清| 丰原市| 巍山| 清镇市| 鲁山县| 黄浦区| 台北市| 临夏市| 盈江县| 漠河县| 剑川县| 图们市| 宿州市| 罗甸县| 海林市| 上高县| 二手房| 临江市|