python 实现多线程下载m3u8格式视频,使用FFmpeg合并(升级修订自s_kangkang_A)

python 实现多线程下载m3u8格式视频,使用FFmpeg合并 如果你需要下载的m3u8文件被加密 请移步:https://blog.youkuaiyun.com/s_kangkang_A/article/details/103163073 电影之类的长视频好像都用m3u8格式了,这就导致了多线程下载视频的意义不是很大,都是短视频,线不线程就没什么意义了嘛。 我们知道,m3u8的链接会下载一个文档,相当长,半小时的视频,应该有接近千行ts链接。 这些ts链接... 阅读详情

基本代码源自:

https://blog.youkuaiyun.com/s_kangkang_A/article/details/103071822。

感谢 s_kangkang_A

https://blog.youkuaiyun.com/s_kangkang_A

在此基础上继续进行了完善:

1、调整了 baseurl 的获取方式,直接从 m3u8 文件的路径中获取 baseurl,这样就把 所有参数 都可以拿到代码外面 进行输入,而无需 每次改代码了

2、改用了eventlet 绿色线程,提高了效率和网络速度

3、增加了 m3u8 的加密处理

4、修订了 存盘文件 名称,可以解决一些 网站使用特殊文件名的问题。

5、修订了 Queue 中的 轮空 的判定方法,改成了 标准 样式。原作的判定方法,曾经用过,特殊条件下会出错的。

 

还在继续努力的,设法能 直接 render 输入网址,自动得到 m3u8 文件,这样就是 全自动了。

需要用 python 3.7以上运行,否则requests就不能正常再 eventlet 中工作。

另外:eventlet 真的是个极品的 "线程"库。已经用了好多年。

# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import absolute_import

import datetime
import os, sys
import re
import threading
#from eventlet.green import threading
import time
from urllib.parse import urlparse
#import requests
import eventlet

if sys.version_info.major < 3:
    import Queue
    import ConfigParser as configparser
else:   
    import queue as Queue
    import configparser

requests = eventlet.import_patched('requests')
 
# 预下载,获取m3u8文件,读出ts链接,并写入文档
def down(headers, url, base_url):
    m3u8_dirname = os.path.dirname (url)
    m3u8_urlp = urlparse (url)
    # 当ts文件链接不完整时,需拼凑
    resp = requests.get(url, headers=headers)
    m3u8_text = resp.text
    # print(m3u8_text)
    # 按行拆分m3u8文档
    ts_queue = eventlet.queue.Queue()
    #ts_queue = eventlet.queue.LifoQueue ()
    #ts_queue = Queue(10000)
    lines = m3u8_text.split('\n')
    s = len(lines)
    # 找到文档中含有ts字段的行
    #concatfile = 'cache/' + "s" + '.txt'
    concatfile = 'cache/' + "decode" + '.m3u8'
    if os.path.exists(concatfile):
        os.remove(concatfile)
    s_count = 1
    for i,line in enumerate(lines):
        #if len(line) >=3 and line[-3:] == '.ts':
        if '.ts' in line:
            if 'http' in line:
                # print("ts>>", line)
                http_line = line
                pass
            else:
                path = os.path.dirname (line)
                if len(path) == 0:
                    http_line = m3u8_dirname + '/' + line
                else:
                    http_line = m3u8_urlp.scheme + '://' + m3u8_urlp.netloc + '' + line
                    #line = base_url + line
            #filename = re.search('([a-zA-Z0-9-_]+.ts)', line).group(1).strip()
            #filename = os.path.basename (line)
            filename = str(s_count).zfill(10)+'.ts'
            if not os.path.exists('cache/' +filename):
                #print ("  Add ", filename)
                #ts_queue.put(line)
                ts_queue.put ((filename, http_line, 0))
            else:
                #print ("  Had ", filename)
                pass
            # print('ts>>',line)

            # 一定要先写文件,因为线程的下载是无序的,文件无法按照
            # 123456。。。去顺序排序,而文件中的命名也无法保证是按顺序的
            # 这会导致下载的ts文件无序,合并时,就会顺序错误,导致视频有问题。
            #open(concatfile, 'a+').write("file %s\n" % filename)
            open(concatfile, 'a+').write("%s\n" % filename)
            #print("\r", '文件写入中', i, "/", s, end="", flush=True)
            s_count += 1
            print("\r", '写入中', s_count, "/", s, http_line, end="", flush=True)
        else:
            # 若发现了 加密 key,则把 key 本地化
            key_re = re.search ("(URI=\".*\.key\")", line)
            if key_re != None:
                key_url = key_re.group(1).strip()
                key_url = key_url[5:-1]
                path = os.path.dirname (key_url)
                if len(path) == 0:
                    http_key = m3u8_dirname + '/' + key_url
                else:
                    http_key = m3u8_urlp.scheme + '://' + m3u8_urlp.netloc + '' + key_url

                key_line = line[:key_re.start()+5] + "key.key" + line[key_re.end()-1:]
                print (line, key_url, http_key, key_line,"\n")

                key_r = requests.get(http_key, stream=True, headers=headers, timeout=(15, 60), verify=True)
                with open('cache/key.key', 'wb') as fp:
                    for chunk in key_r.iter_content(5242):
                        if chunk:
                            fp.write(chunk)
                open(concatfile, 'a+').write(key_line+"\n")
            else:                
                open(concatfile, 'a+').write(line+"\n")
    return ts_queue, concatfile
 
# 线程模式,执行线程下载
def run(ts_queue, headers, pool):
    while True:
        try:
            #url, sleepTime = ts_queue.get (True, 0.5)
            filename, url, sleepTime = ts_queue.get (True, 0.5)
        except Queue.Empty :
            break

        if sleepTime > 0:
            eventlet.sleep (sleepTime)
        #filename = re.search('([a-zA-Z0-9-_]+.ts)', url).group(1).strip()
        #filename = os.path.basename (url)
        requests.packages.urllib3.disable_warnings()

        try:
            r = requests.get(url, stream=True, headers=headers, timeout=(15, 60), verify=False)
            r.raise_for_status ()
            with open('cache/' + filename, 'wb') as fp:
                for chunk in r.iter_content(5242):
                    if chunk:
                        fp.write(chunk)
            print("\r", '任务文件 ', filename, ' 下载成功', pool.running(), ts_queue.qsize(), end="         ", flush=True)
        except Exception as exc:
            print( '任务文件 ', filename, ' 下载失败, 代码:', exc)
            ts_queue.put((filename, url, 5))
            #eventlet.sleep (2)
    #return True
 
# 视频合并方法,使用ffmpeg
def merge(concatfile, name):
    try:
        #path = 'cache/' + name + '.mp4'
        path = 'e:/rm/80s/' + name + '.mp4'
        # command = 'ffmpeg -y -f concat -i %s -crf 18 -ar 48000 -vcodec libx264 -c:a aac -r 25 -g 25 -keyint_min 25 -strict -2 %s' % (concatfile, path)
        command  = "ffmpeg -allowed_extensions ALL -protocol_whitelist \"file,http,crypto,tcp\" "
        #command += ' -y -f concat -i %s -bsf:a aac_adtstoasc -c copy %s' % (concatfile, path)
        command += ' -y -i %s -bsf:a aac_adtstoasc -c copy %s' % (concatfile, path)
        print (command)
        os.system(command)
        print('视频合并完成')
    except:
        print('合并失败')

def remove():
    dir = 'cache/'
    """
    #for line in open('cache/s.txt'):
    for line in open('cache/decode.m3u8'):
        #line = re.search('file (.*?ts)', line).group(1).strip()
        line = re.search('(.*?ts)', line).group(1).strip()
        # print(line)
        os.remove(dir + line)
    print("ts文件全部删除")
    try:
        os.remove('cache/s.txt')
        print('文件删除成功')
    except:
        print('文件删除失败')
    """
    command = "del " + dir + "*/Q"
    os.system(command)

# headers 和 base_url 必须根据实际网站 !手动 ! 设置
if __name__ == '__main__':
    # 测试用链接:https://yiyi.55zuiday.com/ppvod/70B5A6E3A150A99882E28EC793CAF519.m3u8 
    # 链接电影:地球最后的夜晚
    # https://youku.com-ok-sohu.com/20191110/20128_fd24c5a9/1000k/hls/61033a1fdc2000000.ts
    #base_url = 'https://yiyi.55zuiday.com/'
    base_url = 'http://cn5.download05.com/hls/20190721/e7339c09fff1c6c817c2b3cfad9b1d39/1563674290/film_00000.ts'
    headers = {
        #'referer': 'https://yiyi.55zuiday.com/share/wVuAcJFy1tMy4t0x',
        'referer': 'http://www.douying99.com/play/47309_m3u8_0.html',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'
    }

    requests.adapters.DEFAULT_RETRIES = 5

    name = input('请输入视频名称:')
    headers['referer'] = input('请输入网页链接:').strip()
    url = input('请输入视频m3u8链接:').strip()

    start = datetime.datetime.now().replace(microsecond=0)
    print("目录文件开始写入")
    s, concatfile = down(headers, url, base_url)
    print('\n')
    print("目录文件写入结束")
    # 获取队列元素数量
    t_num = s.qsize()
    # 根据数量来开线程数,每五个元素一个线程
    # 最大开到50个
    print("下载任务开始")
    """
    if num > 5:
        t_num = num // 5
    else:
        t_num = 1
    """
    if t_num > 60:
        t_num = 60
    # print(s,concatfile)

    pool = eventlet.GreenPool(t_num)
    run_args={'ts_queue': s, 'headers': headers, 'pool': pool}
    for i in range(t_num):
        pool.spawn_n (run, **run_args)
    pool.waitall()
    """
    threads = []
    for i in range(t_num):
        t = threading.Thread(target=run, name='th-' + str(i), kwargs={'ts_queue': s, 'headers': headers})
        t.setDaemon(True)
        threads.append(t)
    for t in threads:
        time.sleep(0.4)
        t.start()
    for t in threads:
        t.join()
    """
    print('\n')
    print("下载任务结束")
    end = datetime.datetime.now().replace(microsecond=0)
    print('写文件及下载耗时:' + str(end - start))
    merge(concatfile, name)
    remove()
    over = datetime.datetime.now().replace(microsecond=0)
    print('合并及删除文件耗时:' + str(over - end))
    print("所有任务结束 ", name)
    print('任务总时长:', over - start)

 

使用Python写一个m3u8多线程下载器 python 多线程 下载m3u8文件 阅读详情

相关推荐

MP4文件切片生成TS和M3U8文件

1、使用c语言编写 2、可将H264和AAC编码的MP4文件进行切片生成TS文件和M3U8文件,可供HLS播放使用。 3、熟悉ffmpeg可使用ffmpeg切片,但对于像学习的人来说ffmpeg代码太多。 4、使用方式如:./mod_hls *.mp4 ./ ./

python+FFmpeg实现对m3u8文件内的ts视频多线程下载、解密、合并成MP4,并输出。

python+FFmpeg实现对m3u8文件内的ts视频多线程下载、解密、合并成MP4,并输出。

weixin_44002144的博客 8589

python 实现多线程下载m3u8格式视频并使用fmmpeg合并

主要介绍了python 实现多线程下载m3u8格式视频,使用fmmpeg合并的实例代码,需要的朋友可以参考下

多线程you-get 下载b站视频/ffmpeg提取音频/视频/直接请求下载并保存视频/批量移动文件/百度翻译api翻译

分割音频,因为需要分割视频,所以也从分割的视频里直接提前音频。如何使用api可以参考官方文档和demo。同时将翻译结果插入原来文档中,建立新字段。

sueong的博客 1290

Zabbix监控网络设备讲解

Zabbix监控网络设备讲解 本人在研究学习zabbix的时候,网上找过很多如何监控路由,交换,或者是防火墙的文章,但很多都比较散,这里我出一个大概的整合,方便大家参考和学习。本章就拿华三的交换机来做文章。 监控网络设备首先我们需要开启snmp协议,华三怎么开启snmp协议在我的博客里有写到,其次就是找到版本对应的OID,zabbix就是通过抓取设备的OID来做到监控网络设备的,当然zabbix也不仅仅只有通过snmp来监控设备,还有很多别的功能,这些功能我会在以后的博客里面一一更新 文章目录Zab

太阳了文哥的博客 3382

跟着Cell学单细胞转录组分析(五):单细胞转录组marker基因鉴定及细胞群注释

书接上回(跟着Cell学单细胞转录组分析(四):单细胞转录组测序UMAP降维聚类)。完成数据降维和细胞聚类后,最主要的环节和工作就是确定各个细胞群,明确是什么类型的细胞,正群的细胞定群很关键,涉及到整个研究,所以这一步宁愿多费时间,也不要出错。当然,这也不是一蹴而就的,需要反复的确认。 要确定各个群是什么细胞,首先需要了解细胞群的marker基因,因为不同类型的细胞突出 表达的基因也是不同的。这里使用FindAllMarkers鉴定各个细胞群的高表达基因。 DefaultAssay(scedata)

qq_42090739的博客 1万+

多线程下载m3u8影视资源 通过ffmpeg合并ts文件为mp4

多部电影同时下载,每部电影又分多个线程分片下载。

fan7421436的专栏 3266

Ubuntu终端一键安装英伟达驱动:无需手动下载的完整指南

本文提供了一份在Ubuntu系统上通过终端命令一键安装英伟达显卡驱动的完整指南。该方法利用官方PPA源,无需手动下载驱动文件,可自动检测硬件并安装最佳版本,极大简化了流程,适合深度学习环境搭建等场景,有效提升安装效率与稳定性。

weixin_29232121的博客 180

【python】多线程下载m3u8分段视频

Windows系统自带的copy命令也可以合并,但是经过我测试,发现合并之后的视频可能会混乱,所以如果视频比较少,可以借助格式工厂等软件合并,如果较多,可以使用Python操作FFmpeg,但我这里没有实现。有些m3u8是加密的,但会在文件里给出秘钥的url,请求一下即可得到秘钥,秘钥一般是一个数字字母组成的字符串。m3u8一般是以m3u8结尾的文件,如果是浏览器,可以按一下F12打开DevTools进行抓包获取m3u8的完整链接,下载之后提取所有视频分段的uri,为了方便操作,我们可以使用m3u8库。

冰冷的希望的博客 4554

IBM x3650M4服务器更换主板后,导入原有硬盘阵列信息

x3650m4服务器主板坏了,更换好的主板,需要导入原来硬盘的里面的阵列信息 1、开机有提示信息,按C导入配置 2、按Y继续 3、点击start进入阵列卡配置 4、选择configurations 1,点击preview 5、预览硬盘的阵列信息,点击import导入 6、导入成功,可以查看到阵列信息 7、重启服务器,进入操作系统 如果重启找不到操作系统,重启按f12,手动选择从onboard sas controller启动,进入系统一次后面重启就会自动找到并引导系统了。 8、有时候导入阵列

zds00virtue的博客 2万+

头歌MySQL数据库实训答案 有目录

头歌java实训答案集数据库部分一条一条的写,可鼠标手动粘贴,除特定命令外未分大小写。 第1关:创建数据库 第2关创建表 第3关:使用主键约束 第4关:外键约束 第5关:添加常用约束 MySQL数据库 - 数据库和表的基本操作(一) 第1关:查看表结构与修改表名 第2关:修改字段名与字段数据类型 第3关:添加与删除字段 第4关:修改字段的排列位置 第5关:删除表的外键约束 MySQL数据库 - 数据库和表的基本操作(二) 第1关:插入数据 第2关:更新数据 第3关:删除数据 MySQL数据库 - 单表查询(

m0_67401761的博客 4万+

曲线救国-解决FFmpeg下载m3u8视频中途卡住的问题

解决FFmpeg下载m3u8视频中途卡住的问题 , Python 下载m3u8视频,可续传,ts合并mp4。无需改代码,直接命令后加m3u8地址参数就行。

1万+

华为OD机试双机位C卷-字符串解密(Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【字符串解密】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试 - 字符串解密。

qq_45776114的博客 733

使用ffmpeg和python脚本下载网络视频m3u8(全网最全面)

网上给娃找了些好看的电影和一些有趣的短视频,如何保存下来呢?从网上找各种工具?都不方便。于是想到何不编程搞定,搞个脚本。对程序员来说这都不是事儿。且我有华为云服务器,完全可以把地址记下,后台自动下载有空再看。这里总结分享下方法给有需要的小伙伴。

猫哥 的沉淀、积累、总结。天天学习,好好向上...c/c++,嵌入式 linux,Android,HarmonyOS,AIOT) 1万+

DFT笔记 DC/AC mode与Func

DFT scan可以分为DC和AC两种,区别如下图。

m0_61544122的博客 5725

YOLOv8损失函数改进大全:从IoU到FocusIoU的20+种变体全解析(附完整适配代码+性能对比)

目标检测边界框损失函数演进与优化 摘要:边界框损失函数是目标检测模型定位精度的关键因素。本文系统分析了从基础IoU到最新FocusIoU的20余种损失函数的演进历程,包括四代主要技术:基于重叠区域的IoU/GIoU,结合距离度量的DIoU/CIoU,优化形状匹配的EIoU/RIoU,以及考虑方向性的SIoU/WIoU/FocusIoU。针对YOLOv8模型,提供了完整的损失函数实现代码和替换方案,实验表明优化后的损失函数在复杂场景下可提升mAP@0.5达3.2%。文章特别对比了不同损失在小目标、遮挡和密集场

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 996

使用FFmpeg下载m3u8视频并转换为mp4格式

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案,包含了非常先进的音频/视频编解码库libavcodec,有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。

weixin_47078874的博客 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

python多线程下载视频_python 实现多线程下载m3u8格式视频并使用fmmpeg合并

电影之类的长视频好像都用m3u8格式了,这就导致了多线程下载视频的意义不是很大,都是短视频,线不线程就没什么意义了嘛。我们知道,m3u8的链接会下载一个文档,相当长,半小时的视频,应该有接近千行ts链接。这些ts链接下载成ts文件,就是碎片化的视频,加以合并,就成了需要的视频。那,即便网速很快,下几千行视频,效率也就低了,更何况还要合并。我就琢磨了一下午,怎么样才能多线程下载m3u8格式的视频呢?...

weixin_39991055的博客 495

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

python多线程下载m3u8,解密并使用ffmpeg合并ts(解决命令调用ffmpeg报错乱码)

python调用ffmpeg报错 原本我已经安装ffmpeg并且配置环境变量,可以在命令行使用命令但是在pycharm中通过python调用 command = 'ffmpeg -y -f concat -i %s -crf 18 -ar 48000 -vcodec libx264 -c:a aac -r 25 -g 25 -keyint_min 25 -strict -2 %s' % (concatfile, path) os.system(command) 却还是报错“‘ffmpeg’ �����ڲ�

单筱风的博客 3484

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Python批量下载ts视频文件,并用ffmpeg合并

现在很多网络视频被切割成无数个小的ts文件,这篇文件主要是讲怎么下载这些小的ts文件,并按播放顺序,将这些文件下载下来,然后合并成单一完整的视频。

qiuqiuit的专栏 1万+

Python——Windows下载ffmpeg

最近,需要搞一个推拉流,就需要ffmpeg并且,我又看见3B1B用python写的动画,也需要ffmpeg于是,俺就来搞一下,结果网上搞得下载教程,五花八门,把我搞得晕头转向还是用tizi看的国外的。1、下载2、解压后放在对应文件夹下4、配置环境变量就简单的3步,就可以搞定了。

Pan_peter的博客 8585

python爬虫 多线程处理m3u8视频链接的下载,你还在一个一个遍历ts链接慢慢下载?

python爬虫下载视频时多线程处理m3u8视频链接的下载,你还在一个一个遍历ts链接慢慢下载?

Zwq的博客 1069

Python 实现 m3u8 视频下载

Python 实现 m3u8 视频下载

前端开发 5095

通过ffmpeg 下载在线的.m3u8格式视频

ffmpeg 本地安装步骤参照[视频和音频使用ffmpeg进行合并和分离(MP4)]FFmpeg是一款强大的开源视频处理工具,可以通过命令行操作将M3U8转换为MP4;

长缨缚苍龙 3088

ffmpeg 转码及多线程处理

以下为下载ffmpeg的地址: Releases · BtbN/FFmpeg-Builds · GitHubContribute to BtbN/FFmpeg-Builds development by creating an account on GitHub.https://github.com/BtbN/FFmpeg-Builds/releases 下载好相应的版本后,解压即可,添加bin至环境变量 (linux环境变量的添加,详见另一篇文章:优快云https://mp.youkuaiyun.com/

MasterD56的博客 1万+
下一篇: 小米路由作二级路由,挂在上级路由之下,samba能被上级访问
makefool
博客等级 码龄23年 54粉丝 10原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值