如何一次下载.m3u8

Posted

技术标签:

【中文标题】如何一次下载.m3u8【英文标题】:How to download .m3u8 in once time 【发布时间】:2018-04-24 07:17:38 【问题描述】:

我在远程主机上有一个.m3u8 文件,其中包含固定数量的块.ts 文件名,而不是流:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:9.736,
media_0.ts
#EXTINF:9.96,
media_1.ts
#EXTINF:10.0,
media_2.ts
#EXTINF:10.0,
media_3.ts
#EXTINF:10.0,
media_4.ts
#EXTINF:10.2,
media_5.ts
#EXTINF:10.0,

当我使用这个命令时:

# ffmpeg -i "http://example.com/chunklist.m3u8" file.mp4

frame=  582 fps=9.4 q=28.0 size=    1536kB time=00:00:23.21 bitrate= 542.1kbits/s dup=2 drop=4 speed=0.375x

它有效。但它获得逐帧视频并且需要很长时间。 (播放视频几乎需要时间。)

但是由于所有.ts 文件的路径都是已知的。 (http://example.com/media_0.ts, http://example.com/media_1.ts, ...) 必须有一种方法可以同时获取和合并它们。

但是如何直接在ffmpeg 中呢?!

编辑(尝试解决方案):

对于一种解决方案,我知道如何使用 ffmpeg 连接文件。

ffmpeg -i "concat:0.ts|1.ts|2.ts|3.ts|4.ts|5.ts" -c copy output.mp4

这个 ffmpeg 命令很棒,不到 1 秒就可以运行!

所以尝试使用以下命令下载所有带有 CURL 的 .ts 文件:

curl \
http://example.com/media_0.ts -o 0.ts \
http://example.com/media_1.ts -o 1.ts \
http://example.com/media_2.ts -o 2.ts \
http://example.com/media_3.ts -o 3.ts \
http://example.com/media_4.ts -o 4.ts \
http://example.com/media_5.ts -o 5.ts

但是你可以看到结果:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  687k  100  687k    0     0  75108      0  0:00:09  0:00:09 --:--:-- 74111
100  652k  100  652k    0     0  59404      0  0:00:11  0:00:11 --:--:-- 53400
100  673k  100  673k    0     0  48675      0  0:00:14  0:00:14 --:--:-- 55781
100  657k  100  657k    0     0  63573      0  0:00:10  0:00:10 --:--:-- 62494
100  671k  100  671k    0     0  39019      0  0:00:17  0:00:17 --:--:-- 40863
100  692k  100  692k    0     0  63480      0  0:00:11  0:00:11 --:--:-- 80049

看,总下载时间是 72 秒,而所有部分的总持续时间是 59 秒!这个时间很长!

很抱歉,下载所有部分然后连接它,这不是一个好的解决方案。

编辑 2

我尝试在另一台服务器上使用不同的 URL 获取另一个 .m3u8 文件:

一起下载并连接:

ffmpeg -i "concat:\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_0.ts|\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_1.ts|\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_2.ts|\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_3.ts|\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_4.ts|\
http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_5.ts\
" -c copy -y output.ts

另一个带有input.txt URLs 文件的命令。

ffmpeg -f "concat" -i "input.txt" -c copy -y output.ts

input.txt 文件:

file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_0.ts'
file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_1.ts'
file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_2.ts'
file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_3.ts'
file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_4.ts'
file 'http://184.72.239.149/vod/smil:BigBuckBunny.smil/media_w442897525_b560000_5.ts'

如果需要,也可以使用这个命令:

ffmpeg -f "concat" -safe "0" -protocol_whitelist "file,http,https,tcp,tls" -i "input.txt" -c copy -y output.ts

最后,由于下载速度不错,可能我的服务器目标的带宽有限。 :-(

【问题讨论】:

如果你控制服务器端,不如用一个zip压缩包,下载后解压? @DaveS 这是一个坏行为。 ffmpeg -i http://reading/documentation/is/magic/just/try/it/really.m3u8 -c copy file.mp4 【参考方案1】:

从 m3u8 播放列表连接多个视频文件的正确方法是

ffmpeg -i "http://example.com/chunklist.m3u8" -codec copy file.mp4


m3u8 播放列表可以在网络上或本地目录中 它包含相对于播放列表的文件路径列表 -codec copy 避免编码(这需要时间) 容器类型很重要: *.mp4 很好,但是当从网络上获取播放列表时,混合起来似乎有点慢 *.mkv*.ts 最适合我

【讨论】:

【参考方案2】:

你可以试试。

command: ffmpeg -y \ -v warning \ -loglevel debug \ -i "m3u8 url" \ -vcodec copy \ -c copy -f mpegts out.ts

将ts转换为mp4:

ffmpeg -i out.ts -acodec copy -vcodec copy out.mp4

【讨论】:

【参考方案3】:

这里有一些 python 代码,你只需要提供第一个段的 url 和段数(来自 .m3u8 文件):

def dumpSegs(initUrl, n, path, append=False):
    """ downlaod and combine the .ts files
    given the first seg's url, the number of segments and
    the destination download path """
    with open(path, 'ab' if append else 'wb') as f:
        for i in range(1, n + 1):
            segurl = initUrl.replace('seg-1-', 'seg-:d-'.format(i))
            success = False
            while not success:
                try:
                    seg = requests.get(segurl, headers=HEADERS)
                    success = True
                except:
                    print('retrying...')
            f.write(seg.content)

Here 是相同的代码,只是多了一些花里胡哨

【讨论】:

这是第二个仅链接的帖子,广告相同的包裹。这近乎过度的自我推销。您可能想了解(如何不成为垃圾邮件发送者)[***.com/help/promotion]。您为 SO 社区贡献了其他几个很好的答案,所以我不会将其标记为垃圾邮件,但这绝对是一个仅链接的答案。为了改进您的答案并避免删除,我建议您在这篇文章中包含一些相关代码。您的答案应该在没有链接的情况下独立存在。该链接应该只是补充。 很好edit。只需确保您披露该链接指向您的仓库即可。 该问题询问m3u8文件,但您的答案假设m3u8中的所有ts文件都严格遵循模式“seg-1”,可能至少您必须手动提取所有ts链接从m3u8开始

以上是关于如何一次下载.m3u8的主要内容,如果未能解决你的问题,请参考以下文章

linux: m3u8: 如何从 .m3u8 中列出的段手动下载和创建 mp4

ios m3u8格式的视频如何获取他的缩略图

这种m3u8文件怎么下载,记事本打开是这样的。

m3u8视频如何下载到电脑上

苹果cms如何实现在线浏览器播放m3u8格式的电视直播源?

如何解析youku的m3u8文件,拿到mp4文件?