python 玩转m3u8视频

最近在捣鼓视频转码,所谓好记性不如烂笔头,索性把想到的知识点都记录在案吧

现在大多数网站都使用m3u8格式的视频文件,一是体积小,传输快;二是可以切片,提高用户体验。

好了,废话不多说,开始今天的主题:

假如我们在网站上看到一个好的视频,我们想下载下来,怎么办??那这篇文章可以帮助到你(不过你要会使用pthon啊,骚年~~)

先放一张流程图:

 

具体就分这4步,概括一下就是在浏览器中找到这个m3u8文件,下载里面所有的ts文件,最后将所有的ts文件合并为mp4视频。

完整上码

 1 import re
 2 import requests, os
 3 project_path = os.path.abspath(os.path.dirname(__file__))
 4 video_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'video'))
 5 
 6 
 7 class VideoSynthesis:
 8     def __init__(self):
 9         self.header = {
10             'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
11         }
12         self.m3u8_link = 'https://v.pinimg.com/videos/v2/hls/49/3e/6b/493e6bb3f832caf2bef872d648698ff4_hls480w.m3u8'
13         self.base_url = 'https://v.pinimg.com/videos/v2/hls/49/3e/6b/'
14 
15     def get_m3u8_link(self):
16         # 下载m3u8视频
17         m3u8_response = requests.get(url=self.m3u8_link, headers=self.header, verify=False)
18         print(m3u8_response.text)
19         return m3u8_response
20 
21     def handle_m3u8_response(self, m3u8_response):
22         # 处理m3u8响应
23         ts_filename = re.findall('.*?EXTINF:.*?,\n(.*?)\n', m3u8_response.replace(' ', '').replace(r'\n', ''))
24         print(f'tslist: {ts_filename}')
25         ts_link_list = []
26         for item in ts_filename:
27             result_url = self.base_url + item
28             ts_link_list.append(result_url)
29         print(f'ts_link_list: {ts_link_list}')
30         return ts_link_list, ts_filename
31 
32     def download_ts_video(self, ts_url_list, ts_filename):
33         # 通过ts链接下载ts文件
34         for i in range(len(ts_url_list)):
35             ts_url = ts_url_list[i]
36             ts_name = ts_filename[i]
37             try:
38                 response = requests.get(ts_url, stream=True, verify=False)
39             except Exception as e:
40                 print("异常请求:%s" % e.args)
41                 return
42 
43             # 在当前目录下创建个video文件夹
44             ts_path = project_path + r"\video\{}".format(ts_name)
45             with open(ts_path, "wb+") as file:
46                 for chunk in response.iter_content(chunk_size=1024):
47                     if chunk:
48                         file.write(chunk)
49         print("TS文件下载完毕!!")
50 
51     def heBingTsVideo(self):
52         # 视频合成
53         hebing_path = video_path + r"\m3u8_video.mp4"
54         print(hebing_path)
55         all_ts = os.listdir(video_path)
56         with open(hebing_path, 'wb+') as f:
57             for i in range(len(all_ts)):
58                 ts_video_path = os.path.join(video_path, all_ts[i])
59                 f.write(open(ts_video_path, 'rb').read())
60         print("合并完成!!")
61 
62     def run(self):
63         m3u8_response = self.get_m3u8_link()
64         ts_link_list, ts_filename = self.handle_m3u8_response(m3u8_response)
65         
66         # ts_link_list = ['https://v.pinimg.com/videos/v2/hls/49/3e/6b/493e6bb3f832caf2bef872d648698ff4_hls480w00000.ts', 'https://v.pinimg.com/videos/v2/hls/49/3e/6b/493e6bb3f832caf2bef872d648698ff4_hls480w00001.ts', 'https://v.pinimg.com/videos/v2/hls/49/3e/6b/493e6bb3f832caf2bef872d648698ff4_hls480w00002.ts', 'https://v.pinimg.com/videos/v2/hls/49/3e/6b/493e6bb3f832caf2bef872d648698ff4_hls480w00003.ts']
67         # ts_filename = ['493e6bb3f832caf2bef872d648698ff4_hls480w00000.ts', '493e6bb3f832caf2bef872d648698ff4_hls480w00001.ts' ,'493e6bb3f832caf2bef872d648698ff4_hls480w00002.ts', '493e6bb3f832caf2bef872d648698ff4_hls480w00003.ts']
68         
69         self.download_ts_video(ts_link_list, ts_filename)
70         self.heBingTsVideo()
71 
72 
73 if __name__ == '__main__':
74     video_synthesis = VideoSynthesis()
75     video_synthesis.run()

 

视频下载完以后,可能还会遇到压缩,合并问题,那这时候就要用到ffmpeg 这个神器了,直接编写一个脚本就完事了~

 

 1 # coding=utf-8
 2 
 3 import os
 4 
 5 NEW_RESOLUTION = "640x480"  # 目标分辨率,常量
 6 NEW_FPS = 12  # 目标帧率,常量
 7 
 8 curpath = os.getcwd()  # 获取当前路径
 9 input_dir = os.path.join(curpath, "Input_Video")
10 output_dir = os.path.join(curpath, "Output_Video")
11 input_video_list = os.listdir(input_dir)  # 获取视频列表
12 
13 # 如果没有Output_Video这个文件夹,则创建这个文件夹
14 if not os.path.exists(output_dir):
15     os.mkdir(output_dir)
16 
17 # 开始批量二次编码压缩视频转码
18 for each_video in input_video_list:
19     video_name, _ = os.path.splitext(each_video)  # _是没意义,就只是一个无用代号,占个坑而已
20     ffmpeg_command = ("ffmpeg -i %s%s%s -s %s -r %s -y %s%s%s_c.mp4" % (
21         input_dir, os.sep, each_video, NEW_RESOLUTION, NEW_FPS, output_dir, os.sep, video_name))
22     print(ffmpeg_command)
23     os.system(ffmpeg_command)
24 
25 os.system("pause")

注意:这里调用的是系统指令,所以务必使你的ffmpeg.exe执行程序能够被访问到,放到系统全局变量路径下面即可。

 

视频合并

1 ffmpeg -f concat -i filelist.txt -c copy output.mp4
filelist.txt为ffmpeg同级目录下新建记事本,名字随意,而里面的内容长这个样子
file 's1-1.mp4'
file 's1-2.mp4'
file 's1-3.mp4'

注意,如果用这种方式,那么这3个文件也必须存放在同级目录下。如果想使用全路径的形式,比如:file D:\s1\2.mp4'

则应使用下面这条命令

ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4  -- -safe 0 授权进入

 

 

参考文章  https://blog.csdn.net/weixin_38640052/article/details/119680697

      https://blog.csdn.net/human_soul/article/details/103263573

      https://www.cnblogs.com/zipython/p/12920095.html

      https://jingyan.baidu.com/article/2a138328517dce464b134f24.html

      https://blog.csdn.net/winniezhang/article/details/89260841

 

 

 

posted @ 2021-11-24 16:16  查克拉的觉醒  阅读(1182)  评论(0编辑  收藏  举报