使用ffmpeg把mp4与m3u8相互转换的操作(代码片段)

音视频开发老舅 音视频开发老舅     2023-03-31     227

关键词:

FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它提供了录制、转换以及流化音视频的完整解决方案。

一、MP4 转 M3U8

M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码。”M3U” 和 “M3U8” 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。

简单来说,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 一样。

默认的每片长度为 2 秒,m3u8 文件中默认只保存最新的 5 条片的信息,导致最后播放的时候只能播最后的一小部分(直播的时候特别注意)。
-hls_time n 设置每片的长度,默认值为 2,单位为秒。
-hls_list_size n 设置播放列表保存的最多条目,设置为 0 会保存有所片信息,默认值为5。
-hls_wrap n 设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0。这个选项能够避免在磁盘上存储过多的 片,而且能够限制写入磁盘的最多的片的数量。
-hls_start_number n 设置播放列表中 sequence number 的值为 number,默认值为 0。
注意:播放列表的 sequence number 对每个 segment 来说都必须是唯一的,而且它不能和片的文件名(当使用 wrap 选项时,文件名有可能会重复使用)混淆。

2、效率优化版,提升效率

TS 文件是一种媒体的扩展名,它是日本高清摄像机拍摄下进行的封装格式。MPEG2-TS(Transport Stream“传输流”;又称TS、TP、MPEG-TS 或 M2T)是用于音效、图像与数据的通信协定,最早应用于DVD的实时传送节目。MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。

# 1.视频整体转码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 切片时间不准确的问题

播放 m3u8 的 ts 切片,必须要完整的下载一个 ts 切片,才能够播放,设置hls_time 的时间间隔越短越好( 根据实际情况来 ),实际过程中设置切片时间间隔为 2 秒,调用如下指令:

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

但没有按照参数输入,进行切片。

原因:

ts 文件的切割,还跟原文件视频的 GOP 大小有关系(也就是两个 I 帧之间的时间间隔),因为任何一个 ts 分片第一帧必须是I帧,否则无法最快播放,并且第一帧不是 I 帧,对于播放器也是没有任何的意义,直接被播放器扔掉。任何一个视频流必须在获取到第一个I帧才能成功解码出图片。虽然指定了 1 秒切割一个 ts 文件,实际上,由于原视频流可能好几秒才有一个 I 帧,所以必须等到下一个 I 帧,才会重新开始切片。

解决:

既然知道要1秒产生一个ts分片,那就必须产生切片的过程中,强制一秒中产生一个关键帧。

设置关键帧间隔,设置间隔为 2 秒的参数如下:-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

本文福利, 免费领取C++音视频学习资料包、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

 

4、m3u8 格式解析

完整的 m3u8 文件有三部分:

  • index.m3u8,保存视频的基本信息和分段文件顺序;
  • key,如果视频加密,保存密钥;
  • data文件,其他都是视频的数据文件。

具体内容解析:

  • #EXTM3U,是文件开始
  • #EXT-X-VERSION,标识HLS的协议版本号;
  • #EXT-X-TARGETDURATION,表示每个视频分段最大的时长(单位秒);
  • #EXT-X-MEDIA-SEQUENCE,表示播放列表第一个 URL 片段文件的序列号;
  • #EXT-X-PLAYLIST-TYPE,表明流媒体类型;
  • #EXT-X-KEY,加密方式,这里加密方式为AES-128,同时指定IV,在解密时需要;
  • #EXTINF,表示其后 URL 指定的媒体片段时长(单位为秒)。

二、播放演示

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

当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。

在开始一个流媒体会话时,客户端会下载一个包含元数据的 extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。

HLS 只请求基本的 HTTP 报文,与实时传输协议(RTP)不同,HLS 可以穿过任何允许 HTTP 数据通过的防火墙或者代理服务器。

它也很容易使用内容分发网络来传输媒体流。

三、m3u8(ts) 合并为 MP4

远程文件

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 命令如下:

直接转:
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实现代码

$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实现代码

 目录结构
./
  |-- 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()

 原文链接

本文福利, 免费领取C++音视频学习资料包、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓ 

ffmpeg求把m3u8如优酷的转为mp4的命令行

...15分钟左右,看视频文件大小。参考技术A1、安装ffmpeg2、使用转换命令:ffmpeg-i<媒体文件>-strict-2-c:vlibx264-c:aaac-fhls<路径>/test.m3u8例如:ffmpeg-ic:\videos\mp4\test.mp4-strict-2-c:vlibx264-c:aaac-fhlsc:\videos\m3u8\test.m3u8注... 查看详情

将 HLS (m3u8) 转换为 MP4 [关闭]

...造MP4文件(与您通常想要的相反)?假设我有m3u8-有没有使用FFMPEG或其他工具获得单个MP4的简单方法?【问题讨论】:ffmpeg-iin.m3u8-acodeccopy-vcodeccopyout.mp4@szatma 查看详情

使用ffmpeg转码m3u8并播放(代码片段)

...。今天心血来潮又研究了一下,发现还是挺简单的。可以使用ffmpeg工具将mp4格式的视频切片再生成m3u8视频流。m3u8简介:m3u8是苹果公司开发的一项新型播放格式,这种播放格式支持目前市面的windows、and 查看详情

使用 ffmpeg 将 Mp4 转换为 HLS

】使用ffmpeg将Mp4转换为HLS【英文标题】:Mp4toHLSusingffmpeg【发布时间】:2015-09-0322:12:52【问题描述】:我正在尝试在iOS应用中使用ffmpeg将本地.mp4视频转换为HLS。我已经使用pods集成了ffmpeg包装器并生成了所有分段的.ts文件和m3u8文... 查看详情

m3u8格式转换mp4

...OS等平台最为常用。那么,如何将m3u8格式转换mp4呢?推荐使用嗨格式视频转换器,其操作方法比较简单,而且稳定性较强,支持各种视频格式转换。一起来看下具体的操作方法吧~步骤1:打开视频转换工具,进入主界面后点击“... 查看详情

我可以使用网络(没有 ffmpeg)将 m3u8 文件的所有片段下载为一个 mp4 文件吗?

】我可以使用网络(没有ffmpeg)将m3u8文件的所有片段下载为一个mp4文件吗?【英文标题】:CanIdownloadallsegmentsofam3u8fileasonemp4fileusingweb(noffmpeg)【发布时间】:2015-02-2013:56:51【问题描述】:是否可以使用javascript或php将所有m3u8段下... 查看详情

如何把m3u8格式转换成mp4格式?

...是”添加文件夹“,将m3u8的视频文件添加进入,也可以使用拖拽文件的方式将文件拖拽到软件中;步骤3:调整参数选择输出格式视频中的MP4格式,输出目录也可以根据自己的需求自定义一下;步骤4:完成转换视频的相关参数调... 查看详情

m3u8格式转换mp4

...不方便,而且一旦网络卡顿就会导致播放受限。有的时候使用一些工具下载后也不能对m3u8格式进行播放,需要转换为MP4格式才能正常播放。电脑端点击这里免费下载软件—>>万能音频格式转换工具一起来看下具体的操作方法吧~... 查看详情

来自http直播m3u8文件的FFMPEG mp4? [关闭]

】来自http直播m3u8文件的FFMPEGmp4?[关闭]【英文标题】:FFMPEGmp4fromhttplivestreamingm3u8file?[closed]【发布时间】:2015-12-0807:37:22【问题描述】:如何从http直播m3u8文件中提取mp4?我在下面尝试了这个命令:ffmpeg-iinputfile-frawvideo-bsfh264_mp4t... 查看详情

m3u8格式转换mp4

参考技术Am3u8格式转换mp4操作方法如下:操作工具:vivoX9操作系统:FuntouchOS7.127软件:QQ浏览器v8.21、首先打开手机QQ浏览器。2、然后点击“我的”。3、点击“下载管理”。4、可以看到下载好的m3u8格式的视频文件。5、然后长按m3... 查看详情

ffmpeg进行视频切片,生成m3u8

参考技术Ahtml5可直接播放的mp4格式要求视频编码为h.264,音频编码为aac,在转换前可以查看下原视频的编码格式。转换命令命令说明:再将完整的ts文件进行切片处理,命令如下:说明: 查看详情

使用ffmpeg转码mp4至m3u8格式并切片,以及自动检测切片m3u8脚本编写(代码片段)

1,HLS简介HLS,HttpLiveStreaming是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。1.1,m3u8描述文件M3U8文件是指UTF-8编码格式的M3U文... 查看详情

ffmpeg怎么把h264文件转成mp4

...不是视频格式,有些Mp4格式的视频也用这种编码。一般Mp4使用DIVX或XVID编码,主要看播放设备是哪种。ffmpeg需要在命令提示符下运行(按Win键+R调出运行,输入CMD即可),而且要转换的视频最好与FFmpeg放在同一个目录下,以下是... 查看详情

怎样把mov转换成mp4迅捷视频转换器操作方法

使用Mac用户都熟知,MOV是其自带录屏软件QuickTime默认输出视频格式。它是一种有损压缩格式,在Mac端支持较好。但是由于其自身的限制,Mac用户发给Windows用户的MOV视频在对方的播放器中无法播放。MP4是一种几乎在所有平台与设... 查看详情

使用 FFMPEG 将 mp4 转换为最大支持移动设备的 MP4 [关闭]

】使用FFMPEG将mp4转换为最大支持移动设备的MP4[关闭]【英文标题】:Convertmp4tomaximummobilesupportedMP4usingFFMPEG[closed]【发布时间】:2012-11-1316:39:13【问题描述】:我想使用ffmpeg将mp4转换为“小尺寸”mp4...我需要一个带有h263视频和aac音... 查看详情

如何使用 FFMPEG 将 MP4 视频文件转换为 FLV 格式

】如何使用FFMPEG将MP4视频文件转换为FLV格式【英文标题】:HowToConvertMP4VideoFileintoFLVFormatUsingFFMPEG【发布时间】:2012-01-2006:05:15【问题描述】:我必须使用从不同移动设备收到的FFMPEG将MP4视频文件转换为FLV格式。我找到了大部分将... 查看详情

如何使用 ffmpeg 将 MP4 转换为 WMV 以获得更好的质量?

】如何使用ffmpeg将MP4转换为WMV以获得更好的质量?【英文标题】:HowtogetbetterqualityconvertingMP4toWMVwithffmpeg?【发布时间】:2012-06-2005:30:51【问题描述】:我正在使用以下两个缩放命令将MP4文件转换为WMV:ffmpeg-itest.mp4-y-vfscale=-1:360test... 查看详情

mp4视频格式怎么转换

推荐使用嗨格式视频转换器,支持1000+音视频转换功能,高精度转换视频清晰不模糊无锯齿,流畅不丢帧无卡顿,操作简单功能强大。软件特色:①功能丰富,多种格式高清无损转换常见音视频格式高清转换、视频压缩、音频提... 查看详情