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


Posted in Python onNovember 15, 2019

电影之类的长视频好像都用m3u8格式了,这就导致了多线程下载视频的意义不是很大,都是短视频,线不线程就没什么意义了嘛。

我们知道,m3u8的链接会下载一个文档,相当长,半小时的视频,应该有接近千行ts链接。

这些ts链接下载成ts文件,就是碎片化的视频,加以合并,就成了需要的视频。

那,即便网速很快,下几千行视频,效率也就低了,更何况还要合并。我就琢磨了一下午,怎么样才能多线程下载m3u8格式的视频呢?

先上代码,再说重难点:

import datetime
import os
import re
import threading
import requests
from queue import Queue
# 预下载,获取m3u8文件,读出ts链接,并写入文档
def down():
  # m3u8链接
  url = 'https://ali-video.acfun.cn/mediacloud/acfun/acfun_video/segment/3zf_GAW6nFMuDXrTLL89OZYOZ4mwxGoASH6UcZbsj1_6eAxUxtp3xm8wFmGMNOnZ.m3u8?auth_key=1573739375-474267152-0-a5aa2b6df4cb4168381bf8b04d88ddb1'
  # 当ts文件链接不完整时,需拼凑
  # 大部分网站可使用该方法拼接,部分特殊网站需单独拼接
  base_url = re.split(r"[a-zA-Z0-9-_\.]+\.m3u8", url)[0]
  # print(base_url)
  resp = requests.get(url)
  m3u8_text = resp.text
  # print(m3u8_text)
  # 按行拆分m3u8文档
  ts_queue = Queue(10000)
  lines = m3u8_text.split('\n')
  # 找到文档中含有ts字段的行
  concatfile = 'cache/' + "s" + '.txt'
  for line in lines:
    if '.ts' in line:
      if 'http' in line:
        # print("ts>>", line)
        ts_queue.put(line)
      else:
        line = base_url + line
        ts_queue.put(line)
        # print('ts>>',line)
      filename = re.search('([a-zA-Z0-9-]+.ts)', line).group(1).strip()
      # 一定要先写文件,因为线程的下载是无序的,文件无法按照
      # 123456。。。去顺序排序,而文件中的命名也无法保证是按顺序的
      # 这会导致下载的ts文件无序,合并时,就会顺序错误,导致视频有问题。
      open(concatfile, 'a+').write("file %s\n" % filename)
  return ts_queue,concatfile
# 线程模式,执行线程下载
def run(ts_queue):
  tt_name = threading.current_thread().getName()
  while not ts_queue.empty():
    url = ts_queue.get()
    r = requests.get(url, stream=True)
    filename = re.search('([a-zA-Z0-9-]+.ts)', url).group(1).strip()
    with open('cache/' + filename, 'wb') as fp:
      for chunk in r.iter_content(5242):
        if chunk:
          fp.write(chunk)
    print(tt_name + " " + filename + ' 下载成功')
# 视频合并方法,使用ffmpeg
def merge(concatfile, name):
  try:
    path = 'cache/' + 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)
    os.system(command)
    print('视频合并完成')
  except:
    print('合并失败')
if __name__ == '__main__':
  name = input('请输入视频名称:')
  start = datetime.datetime.now().replace(microsecond=0)
  s,concatfile = down()
  # print(s,concatfile)
  threads = []
  for i in range(15):
    t = threading.Thread(target=run, name='th-'+str(i), kwargs={'ts_queue': s})
    threads.append(t)
  for t in threads:
    t.start()
  for t in threads:
    t.join()
  end = datetime.datetime.now().replace(microsecond=0)
  print('下载耗时:' + str(end - start))
  merge(concatfile,name)
  over = datetime.datetime.now().replace(microsecond=0)
  print('合并耗时:' + str(over - end))

效果图:

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

代码开始:自己输入视频名称(也可以去原网站爬名称)

查看下载耗时,fmmpeg开始合并:

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

合并耗时:

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

7分多钟,90个ts文件,接近40MB。两秒下载完成。

更大的文件,开更多的线程。

然后我们画画重难点:

第一:ts文件命名问题。

我们知道,每一个线程启动,除了队列不会重复,那么代码里都会重新跑(线程里的代码),那么,1.ts,2.ts....这种命名是不可能的了,文件会被覆盖。命名我使用了ts链接中的部分链接。

第二:合并问题。

文件的合并是根据文档内的顺序,也就是,如果边下载边合并,那么,线程的无序性导致下载无序,文件写入也就无序化了,合并时,时间线会错误,合出来的视频就无法看。因此,文件要提前写好才行,这和命名有很大的关联,看代码即知。

第三:有的m3u8是特殊处理的,代码具有一定的局限性。

写的时候挺难的,脑子都乱了,就这些吧,记录一下。

对了,贴一下下载的图:90个ts文件,一个mp4文件,一个文档。

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

总结

以上所述是小编给大家介绍的python 实现多线程下载m3u8格式视频并使用fmmpeg合并,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
Python制作CSDN免积分下载器
Mar 10 Python
分享几道你可能遇到的python面试题
Jul 24 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
Jan 26 Python
python 接口返回的json字符串实例
Mar 27 Python
python 将字符串完成特定的向右移动方法
Jun 11 Python
Django中celery执行任务结果的保存方法
Jul 12 Python
Python中变量的输入输出实例代码详解
Jul 28 Python
pytorch点乘与叉乘示例讲解
Dec 27 Python
python实现多进程按序号批量修改文件名的方法示例
Dec 30 Python
python使用Thread的setDaemon启动后台线程教程
Apr 25 Python
解决python3.6用cx_Oracle库连接Oracle的问题
Dec 07 Python
用Python编写简单的gRPC服务的详细过程
Jul 04 Python
浅析python内置模块collections
Nov 15 #Python
Python树莓派学习笔记之UDP传输视频帧操作详解
Nov 15 #Python
Python numpy数组转置与轴变换
Nov 15 #Python
python修改文件内容的3种方法详解
Nov 15 #Python
Python实现基于socket的udp传输与接收功能详解
Nov 15 #Python
python根据文本生成词云图代码实例
Nov 15 #Python
解决django后台管理界面添加中文内容乱码问题
Nov 15 #Python
You might like
全国FM电台频率大全 - 4 山西省
2020/03/11 无线电
PHP 遍历XP文件夹下所有文件
2008/11/27 PHP
PHP CLI模式下的多进程应用分析
2013/06/03 PHP
CodeIgniter错误mysql_connect(): No such file or directory解决方法
2014/09/06 PHP
phpstudy的php版本自由修改的方法
2017/10/18 PHP
PHP分页显示的方法分析【附PHP通用分页类】
2018/05/10 PHP
javascript css float属性的特殊写法
2008/11/13 Javascript
javascript document.compatMode兼容性
2010/02/23 Javascript
在图片上显示左右箭头类似翻页的代码
2013/03/04 Javascript
推荐8款jQuery轻量级树形Tree插件
2014/11/12 Javascript
JS组件Bootstrap dropdown组件扩展hover事件
2016/04/17 Javascript
js 连续赋值的简单实现
2016/06/13 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
微信小程序 教程之WXSS
2016/10/18 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
前端开发不得不知的10个最佳ES6特性
2017/08/30 Javascript
vue登录路由验证的实现
2017/12/13 Javascript
利用Node.js批量抓取高清妹子图片实例教程
2018/08/02 Javascript
JS数组进阶示例【数组的几种函数用法】
2020/01/16 Javascript
云服务器部署Node.js项目的方法步骤(小白系列)
2020/03/23 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
jQuery实现的移动端图片缩放功能组件示例
2020/05/01 jQuery
Python 列表list使用介绍
2014/11/30 Python
Python元组操作实例分析【创建、赋值、更新、删除等】
2017/07/24 Python
python实现冒泡排序算法的两种方法
2018/03/10 Python
pyqt5 实现 下拉菜单 + 打开文件的示例代码
2019/06/20 Python
如何基于pythonnet调用halcon脚本
2020/01/20 Python
vscode+PyQt5安装详解步骤
2020/08/12 Python
浅析python中的del用法
2020/09/02 Python
浅析css3中matrix函数的使用
2016/06/06 HTML / CSS
CSS3+JavaScript实现炫酷呼吸效果的示例代码
2020/06/15 HTML / CSS
HTML5实现的图片无限加载的瀑布流效果另带边框圆角阴影
2014/03/07 HTML / CSS
纬创Java面试题笔试题
2014/10/02 面试题
应聘自荐书
2013/10/08 职场文书
小学校长汇报材料
2014/08/20 职场文书
护士优质服务演讲稿
2014/08/26 职场文书