热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

m3u8转mp4缓存合并工厂_使用Python下载M3U8格式视频

作者简介本篇文章来自MRArchive的投稿,分享了如何使用Python下载M3U8格式的视频,希望对大家有所帮助!同时也感谢作者贡献的精
543ed0bc37b628392e130b51134f8e63.png

/  作者简介  /

本篇文章来自 MRArchive 的投稿,分享了如何使用Python下载M3U8格式的视频,希望对大家有所帮助!同时也感谢作者贡献的精彩文章。

作者信息

网站:https://toodo.fun

B站:https://space.bilibili.com/314191627

/  背景简介  /

M3U 是一种播放多媒体列表的文件格式,它的设计初衷是为了播放音频文件,比如MP3,但是越来越多的软件现在用来播放视频文件列表,M3U也可以指定在线流媒体音频源。很多播放器和软件都支持M3U文件格式。

m3u8 文件是 HTTP Live Streaming(缩写为 HLS) 协议的部分内容,而 HLS 是一个由苹果公司提出的基于 HTTP 的流媒体网络传输协议。

HLS 是新一代流媒体传输协议,其基本实现原理为将一个大的媒体文件进行分片,将该分片文件资源路径记录于 m3u8 文件(即 playlist)内,其中附带一些额外描述(比如该资源的多带宽信息···)用于提供给客户端。客户端依据该 m3u8 文件即可获取对应的媒体资源,进行播放。

扩展M3U指令:

#EXTM3U //必需,表示一个扩展的m3u文件

#EXT-X-VERSION:3 //hls的协议版本号,暗示媒体流的兼容性

#EXT-X-MEDIA-SEQUENCE:xx //首个分段的sequence number

#EXT-X-ALLOW-CACHE:NO //是否缓存

#EXT-X-TARGETDURATION:5 //每个视频分段最大的时长(单位秒)

#EXT-X-DISCONTINUITY //表示换编码

#EXTINF: //每个切片的时长

/  获取.m3u8文件中的视频信息  /

.m3u8文件储存了视频所在的位置信息,我们可以通过发送一个Get请求来获取链接中的内容:

content = requests.get(m3u8Url).text

/  拼接视频下载链接  /

我们通过得到的视频信息进行视频网址拼接,.m3u8文件中的链接可以为全路径或者相对路径,所以我们判断后进行拼接并存入一个列表当中:

urls = []for index, video in enumerate(content.split('\n')): if '#EXTINF' in video: if content[index + 1][0] == '/': downloadLink = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + content[index + 1] elif content[index + 1][:4] == 'http': downloadLink = content[index + 1] else: downloadLink = url.replace(url.split('/')[-1], content[index + 1]) urls.append(downloadLink)

/  使用多线程下载视频  /

得到视频列表后,我们就可以对视频进行下载了,为了提高下载效率,我们可以使用多线程进行下载:

def download(downloadLink, name): for _ in range(10): try: req = requests.get(downloadLink, headers=headers, timeout=15).content with open(f"{name}", "wb") as f: f.write(req) f.flush() break except: if _ == 9: print(f"{name}下载失败") else: print(f"{name}正在进行第{_}次重试")pool = ThreadPoolExecutor(max_workers=threadNum)futures = []for index, downloadLink in enumerate(urls): fileList.append(os.path.basename(downloadLink)) futures.append(pool.submit(download, downloadLink, f"{downloadPath}/{os.path.basename(downloadLink)}"))wait(futures)

/  合并视频  /

等待全部下载完成后,是一个个的ts视频文件,然后我们再将这些文件合并成一个视频文件,此时要注意视频的顺序,我们可以在我们的视频列表中依次取出进行合并

def merge_file(path, name): global fileList cmd = "copy /b " for i in fileList: if i != fileList[-1]: cmd += f"{i} + " else: cmd += f"{i} {name}" os.chdir(path) with open('combine.cmd', 'w') as f: f.write(cmd) os.system("combine.cmd") os.system('del /Q *.ts') os.system('del /Q *.cmd')

这里我们是写了一个脚本来完成合并的任务,使用命令'copy /b file1 + file2 +... + fileN newFile'进行合并,并于完成后将ts小文件进行了删除。至此,视频就下载完成了。

/  完整代码如下  /

import requestsimport osfrom concurrent.futures import ThreadPoolExecutor, waitimport sysfinishedNum = 0allNum = 0fileList = []headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'}def download(downloadLink, name): global finishedNum global allNum for _ in range(10): try: req = requests.get(downloadLink, headers=headers, timeout=15).content with open(f"{name}", "wb") as f: f.write(req) f.flush() finishedNum += 1 print(f"{name}下载成功, 总进度{round(finishedNum / allNum * 100, 2)}% ({finishedNum}/{allNum})") break except: if _ == 9: print(f"{name}下载失败") else: print(f"{name}正在进行第{_}次重试")def merge_file(path, name): global fileList cmd = "copy /b " for i in fileList: if i != fileList[-1]: cmd += f"{i} + " else: cmd += f"{i} {name}" os.chdir(path) with open('combine.cmd', 'w') as f: f.write(cmd) os.system("combine.cmd") os.system('del /Q *.ts') os.system('del /Q *.cmd')def downloader(url, name, threadNum): global allNum global fileList print("读取文件信息中...") downloadPath = 'Download' if not os.path.exists(downloadPath): os.mkdir(downloadPath) # 查看是否存在 if os.path.exists(f"{downloadPath}/{name}"): print(f"视频文件已经存在,如需重新下载请先删除之前的视频文件") return content = requests.get(url, headers=headers).text.split('\n') if "#EXTM3U" not in content[0]: raise BaseException(f"非M3U8链接") # .m3u8 跳转 for video in content: if ".m3u8" in video: if video[0] == '/': url = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + video elif video[:4] == 'http': url = video else: url = url.replace(url.split('/')[-1], video) print(url) content = requests.get(url, headers=headers).text.split('\n') urls = [] for index, video in enumerate(content): if '#EXTINF' in video: if content[index + 1][0] == '/': downloadLink = url.split('//')[0] + "//" + url.split('//')[1].split('/')[0] + content[index + 1] elif content[index + 1][:4] == 'http': downloadLink = content[index + 1] else: downloadLink = url.replace(url.split('/')[-1], content[index + 1]) urls.append(downloadLink) allNum = len(urls) pool = ThreadPoolExecutor(max_workers=threadNum) futures = [] for index, downloadLink in enumerate(urls): fileList.append(os.path.basename(downloadLink)) futures.append(pool.submit(download, downloadLink, f"{downloadPath}/{os.path.basename(downloadLink)}")) wait(futures) print(f"运行完成") merge_file(downloadPath, name) print(f"合并完成") print(f"文件下载成功,尽情享用吧")if __name__ == '__main__': videoUrl = str(sys.argv[1]) name = str(sys.argv[2]) threadNum = int(sys.argv[3]) downloader(videoUrl, name, threadNum)

/  打包好的Windows版软件下载  /

百度云下载地址:https://pan.baidu.com/s/1ZsPb9WTmYP8VUKuR9tuoyw 提取码:mxb6

蓝奏云下载地址:https://lanzous.com/icnc1ve




推荐阅读
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 本文回顾了作者初次接触Unicode编码时的经历,并详细探讨了ASCII、ANSI、GB2312、UNICODE以及UTF-8和UTF-16编码的区别和应用场景。通过实例分析,帮助读者更好地理解和使用这些编码。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 本文详细介绍了在Linux系统上编译安装MySQL 5.5源码的步骤。首先,通过Yum安装必要的依赖软件包,如GCC、GCC-C++等,确保编译环境的完备。接着,下载并解压MySQL 5.5的源码包,配置编译选项,进行编译和安装。最后,完成安装后,进行基本的配置和启动测试,确保MySQL服务正常运行。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
author-avatar
那是黑夜过后的黎明_182
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有