音视频处理(三):hls协议和m3u8详解和视频下载爬虫实战

文章目录

  • 一、背景
  • 二、HLS协议
  • 三、M3U8文件
  • 四、TS视屏流封装格式
    • 4.1 TS层
    • 4.2 PES层
    • 4.3 ES层
  • 五、m3u8和mp4转换
    • 5.1 mp4转m3u8
    • 5.2 m3u8转mp4
  • 六、HLS vs RTSP
    • 6.1 RTSP(Real Time Streaming Protocol)
    • 6.2 HLS 和 RTSP对比
      • 应用场景
      • 发展趋势
  • 七、电视迷视频下载实战
    • 7.1 网页分析
    • 7.2 爬虫方案
    • 7.3 解析index.m3u8
    • 7.4 解析mixed.m3u8
    • 7.5 去菠菜广告视频
  • 八、参考链接

一、背景

当前很多视频网站使用m3u8文件进行视频播放,m3u8文件时hls(http live stream)协议的一部分,传统的rtsp协议对于http视频播放场景网络不佳的场景没法做到动态自适应分辨率,而且当前浏览器没有天然支持rtsp协议,所以苹果公司推出hls协议,使用播放列表m3u8文件和ts文件实现http的视频播放技术。本文详细介绍一下hls协议,对比一下hls和rtsp的差异,并且以电视迷网站视频下载做m3u8视频文件下载的实战介绍。

二、HLS协议

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

hls = m3u8文件 + ts视频流

工作原理:

  1. 切片(Segmentation): 视频源(如直播流或点播文件)被编码器实时地切割成一系列小的、连续的 TS 格式视频文件片段(例如每个片段时长2-10秒)。
  2. 创建索引(Playlist): 同时,编码器会生成一个不断更新的索引文件(M3U8 格式的播放列表)。这个文件记录了所有 TS 片段的URL和元数据(如码率、分辨率)。
  3. 分发(Distribution): 这些 TS 片段和 M3U8 文件通过标准的 HTTP 服务器分发,就像分发普通的网页图片一样。
  4. 播放(Playback): 播放器(如浏览器中的 video.js 或移动端播放器)首先下载 M3U8 文件,然后按顺序下载 TS 片段,并逐个播放,实现无缝的视频观看体验。

优点:

  • 高兼容性/穿透性: 使用 HTTP 协议,可以轻松通过任何防火墙或代理服务器,因为互联网就是为 HTTP 优化的。
  • 强大的自适应能力: HLS 的核心特性。编码器可以生成同一视频内容、不同码率(如 1080p、720p、480p)的多套 TS 片段和对应的 M3U8 文件。播放器可以根据当前网络状况自动选择最合适的码流进行下载,保证流畅播放。
  • 高可靠性: 基于 TCP 的 HTTP 协议确保了数据传输的可靠性,即使网络有波动,也只会导致下载变慢,而不是数据丢失。
  • 易于缓存和CDN加速: 视频片段是静态的 HTTP 资源,可以被广泛分布的 CDN 节点缓存,极大减轻源站压力。

缺点:

  • 高延迟: 这是 HLS 最大的缺点。延迟来源于"切片时间 + 缓冲区时间"。为了确保流畅性,播放器通常会预先下载好几个片段,导致延迟远大于单个片段的时长,通常在 10 秒以上。虽然通过低延迟 HLS 技术可以优化到 3 秒左右,但依然不如 RTSP。

三、M3U8文件

HLS协议中,使用m3u8文件来保存播放列表,m3u8文件是extend M3U (MP3 URL) files文件,其中8表示使用utf8编码,m3u文件最初是用于传输mp3文件列表信息,扩展后可以用来传输视频信息。m3u8文件内容格式如下,其中保存了具体视频ts的url,浏览器下载m3u8文件后根据url下载对应的ts文件进行播放。

复制代码
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:8
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
b9754d299d5000000.ts
#EXTINF:4.080000,
b9754d299d5000001.ts
#EXTINF:3.960000,
b9754d299d5000002.ts
#EXT-X-ENDLIST

EXTM3U: 表示这是一个m3u8文件,必须在文件的第一行,所有的M3U8文件中必须包含这个标签。

EXT-X-ENDLIST:切片序列结束的标记。

XT-X-VERSION:文件版本,常见是3

EXT-X-PLAYLIST-TYPE:播放列表类型,常见是VOD。

EXT-X-MEDIA-SEQUENCE:播放的序列号。

EXT-X-TARGETDURATION:该标签指定了媒体文件持续时间的最大值,播放文件列表中的媒体文件在EXTINF标签中定义的持续时间必须小于或者等于该标签指定的持续时间。该标签在播放列表文件中必须出现一次。

EXT-X-DISCONTINUITY:通知播放器解码时清除缓存,画面与前面可能存在较大差异,编码、分别率可能变化等,比如在视频中插入广告。

EXTINF: 里面保存的视频序列,格式如下:先是说明视频的长度,然后使用逗号分隔,后面跟ts文件的链接。

复制代码
#EXTINF:4.000000,
b9754d299d5000000.ts

上述ts链接是本地文件名,使用网络传输时需要使用浏览器js脚本下ts播放,另外一种方式是m3u8文件中固定好ts的网络url,如下方式,但是这种对于生成m3u8文件就会复杂一些,并且不利于cdn解析。

复制代码
#EXTINF:4.000000,
http://test.com/b9754d299d5000000.ts

客户端播放M3U8的文件的一些注意事项:

  1. 分片必须是动态改变的,序列不能相同,并且序列必须是增序的。
  2. 当M3U8没有出现EXT-X-ENDLIST标签时,无论这个M3U8列表中有多少分片,播放分片都是从倒数第三片开始播放,如果不满三片则不应该播放。当然如果有些播放器做了特别定制了,则可以不遵照这个原则。
  3. 以播放当前分片的duration时间刷新M3U8列表,然后做对应的加载动作。
  4. 前一片分片和后一片分片有不连续的时候,播放可能会出错,那么需要X-DISCONTINUTY标签来解决这个错误。
  5. 如果播放列表在刷新之后与之前的列表相同,那么在播放当前分片duration一半的时间内在刷新一次。
  • 扩展的m3u8属性EXT-X-STREAM-INF

EXT-X-STREAM-INF标签出现在M3U8时,主要是出现在多级M3U8文件中时,例如M3U8中包含子M3U8列表,或者主M3U8中包含多码率M3U8时;该标签后需要跟一些属性,下面就来逐一说明一下这些属性:

  1. BANDWIDTH:BANDWIDTH的值为最高码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的最大码率(必要参数)。
  2. AVERAGE-BANDWIDTH:AVERAGE-BANDWIDTH的值为平均码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的平均码率。(可选参数)。
  3. CODECS:CODECS的值用于声明EXT-X-STREAM-INF下面对应M3U8里面的音视频编码、视频编码的信息(可选参数)。
  4. RESOLUTION:M3U8中视频的宽高信息描述(可选参数)。
  5. FRAME-RATE:子M3U8中的视频帧率(可选参数)。

比如:如下index.m3u8中包含一个实际的mixed.m3u8文件路径。

复制代码
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608
2000k/hls/mixed.m3u8

四、TS视屏流封装格式

TS是mpeg-ts格式视频流封装格式,而非压缩格式,每个ts片段可以独立解码。对应ITU规范是H.222 H.222.0 : Information technology - Generic coding of moving pictures and associated audio information: Systems。ts配合m3u8中可以保存多份不同码流的ts文件,实现自适应码流 的作用,客户端根据播放进度和下载速度进行自行选择。并且ts文件可以部署在cdn服务器上,服务器只需要提供m3u8文件,大大减小了服务器的压力。

那么ts文件格式到底是怎样的呢?

ts和mp4一样都是视频流封装格式,而不是编码技术,其内部 封装的视频流

视频编码是H.264,音频是AAC,MP3, AC-3或者EC-3格式。

MPEG-TS

mpeg2-ts格式,ts(Transport Stream)主要用于视频传输用。mpeg2定义两种流封装格式:

  • PS (Program Stream)节目流:用于存储固定时长的视频,如光盘,

  • TS(Transport Stream)主要用于实时传送的节目。通常TS流的后缀是.ts、.mpg或者.mpeg

TS文件(码流)可以分为三层。

  • TS层(Transport Stream):最外层的封装格式,流识别和传输的信息。

  • PES层(Packet Elemental Stream):音视频数据+时间戳。

  • ES层(Elementary Stream):音视频数据。

4.1 TS层

TS层分为三个部分:TS Header、Adaptation Field、Payload。每个ts报文长度是188字节。

TS Header固定4个字节,Adaptation Field是可选的,主要作用是给不足188字节的数据做填充;其中Payload保存的是PES数据。

ts header中关键的字段如下:

  • PID

表示报文类型,包括:PAT、CAT、NIT、PMT、以及媒体数据。其中比较重要的是PAT表和PMT表。 PID值如下,如果PID不是下表中的值,表示的是节目的唯一标识。

解析TS流要先找到PAT表,只要找到PAT就可以找到PMT,然后就可以找到音视频流了。

PAT表和PMT表需要定期插入TS流,因为用户随时可能加入TS流,这个间隔很小,通常每隔几个视频帧就要加入PAT和PMT。其中,PAT和PMT是必须的,还可以加入其他表如SDT(业务描述表)等,不过,HLS流只要PAT和PMT就可以了。

  • PCR

PCR是时钟参考。

  • PAT表

节目关联表(Program Association Table, PAT),对应的是以前电视节目直播,用来描述ts流中有几个节目。

  • PMT表

节目映射表(PMT)的意义在于它给出了节目号与组成这个节目元素之间的映射,也就是说PMT是连接节目号与节目元素的桥梁。

我们知道一个电视节目至少包含了视频和音频数据,而每一个节目的视音频数据都是以包的形式在TS流中传输的,所以说一个TS流包含了多个节目的视频和音频数据包。

节目映射表的 PID 是由 PAT 表提供给出的,表征一路节目所有流信息,包含:VideoPID、AudioPID、DataPID。

  • adaptation field

在一个帧的第一个ts包和最后一个ts包中,中间的ts不加。

4.2 PES层

PES层是在每一个视频/音频帧上加入了时间戳等信息,PES的帧头如下:

主要有两个时间戳:

  • pts:显示时间戳
  • dts:解码时间戳

视频数据两种时间戳都需要,音频只需要pts。pts和dts是由于h.264中的B帧引入的,B帧需要前后帧都进行参考然后进行解码,所以解码时间戳比显示时间戳会提前一点,而I帧和P帧都是只依赖之前的帧,所以pts和dts是一样的。

点播视频dts算法

dts = 初始值 + 90000 / video_frame_rate,初始值可以随便指定,但是最好不要取0,video_frame_rate就是帧率,比如23、30。pts和dts是以timescale为单位的,1s = 90000 time scale , 一帧就应该是90000/video_frame_rate 个timescale。用一帧的timescale除以采样频率就可以转换为一帧的播放时长。

4.3 ES层

ES层是具体的音视频数据,如视频的H.264,音频的AAC。

打包视频流h.264s时需要加上nalu层(Network Abstraction Layer unit),nalu包括start code和nalu header,start code固定为0x00000001(帧开始)或0x000001(帧中)。h.264的数据是由slice组成的,slice的内容包括:视频、sps、pps等。nalu type决定了后面的h.264数据内容。而音频数据则要加上adts(Audio Data Transport Stream)头。

  • TS 流生成流程

将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。

对ES(基本码流)进行打包形成PES。

在PES包中加入时间戳信息(PTS/DTS)。

将PES包内容分配到一系列固定长度的传输包(TS Packet)中。

在传输包中加入定时信息(PCR)。

在传输包中加入节目专用信息(PSI) 。

连续输出传输包形成具有恒定比特率的MPEG-TS流。

  • TS 流解析流程

复用的MPEG-TS流中解析出TS包;

从TS包中获取PAT及对应的PMT;

从而获取特定节目的音视频PID;

通过PID筛选出特定音视频相关的TS包,并解析出PES;

从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;

将ES交给解码器,获得压缩前的原始音视频数据。

五、m3u8和mp4转换

可以使用ffmpeg工具对mp4和m3u8文件之间互相转换。

5.1 mp4转m3u8

ffmpeg 可以将mp4生成m3u8文件和ts文件命令如下:

复制代码
ffmpeg -re -i 好汉歌.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8

因为ffmpeg 默认的list size 为5,所以只获得最后的5个片段。为了解决这个问题,需要指定参数-hls_list_size 0,这样就能包含所有的片段

复制代码
ffmpeg -re -i 好汉歌.mp4 -c copy -f hls -hls_list_size 0 -bsf:v h264_mp4toannexb output.m3u8

hls_time参数用于设置M3U8列表中切片的duration。

hls_base_url: 指定网络路径,可以用于网络上的m3u8文件。

5.2 m3u8转mp4

tips:m3u8 可能需要key,ffmepg命令将m3u8转成mp4。

复制代码
ffmpeg -i https://vip.ffzy-online4.com/20230224/10825_cf435d2c/index.m3u8?sign=30db3fb63fd9b8e8edc7d1c02785f9d2 -c copy xiaoaojianghu_43.mp4

六、HLS vs RTSP

关于实时直播,第一时间会想到使用最多的RTSP,那么HLS和RTSP有什么区别呢?

6.1 RTSP(Real Time Streaming Protocol)

RTSP的工作原理:

  1. 建立连接 : 播放器向流媒体服务器发起 RTSP 连接(例如 rtsp://server.com/stream)。
  2. 协商参数(DESCRIBE, SETUP): 通过 RTSP 命令,客户端和服务器协商传输参数(如视频编码、传输协议)。
  3. 传输数据(PLAY) : 客户端发送 PLAY命令后,服务器开始通过 RTP 协议(通常基于 UDP)将流数据包源源不断地推送给客户端。同时,RTCP协议用于传输控制信息(如网络状况反馈)。
  4. 控制播放(PAUSE, TEARDOWN): 客户端可以通过 RTSP 命令暂停或终止流。

优点:

  • 低延迟: 由于是实时的数据流推送,几乎没有切片和缓冲带来的延迟,非常适合实时交互场景。
  • 高效率: 基于 UDP 的 RTP 传输避免了 TCP 的重传机制,在良好网络下延迟更稳定。
  • 支持点对点控制: 原生支持播放、暂停、快进等 VCR 式操作。

缺点:

  • 兼容性差: 现代网页浏览器(Chrome, Firefox, Safari)都不再原生支持 RTSP,需要借助 Flash、浏览器插件或将流转码为 HLS/MPEG-DASH 才能在网页中播放。
  • 防火墙/NAT 穿透困难: RTSP/RTP 使用非标准端口或动态端口,在企业防火墙或 NAT 后很容易被阻挡。
  • 不支持自适应码率: RTSP 本身没有内置自适应码率切换机制,需要依赖外部系统(如监控领域的流媒体服务器)来实现多码率切换。

6.2 HLS 和 RTSP对比

HLS 是为"分发"和"兼容性"而生的互联网协议,而 RTSP 是为"实时"和"控制"而生的专业流媒体协议。

特性 HLS RTSP
全称 HTTP Live Streaming Real Time Streaming Protocol
核心原理 将视频切片成小文件(.ts),通过HTTP下载播放 建立专有连接,实时传输流数据(如RTP)
协议基础 HTTP(基于TCP) RTSP、RTP、RTCP(通常基于UDP,也可用TCP)
延迟 (通常10-30秒或更高) (通常1-3秒,可低于500毫秒)
适应性 极强,天生支持自适应码率(ABR) ,通常需要外部系统支持
防火墙/NAT穿透 极佳(使用标准HTTP 80/443端口) 较差(使用动态端口范围,容易被防火墙阻挡)
主要应用场景 点播视频(优酷、YouTube)、直播(Twitch)、广播电视 视频监控(IPCAM)、视频会议、移动应用(如FaceTime)
兼容性 极佳,所有现代浏览器、移动设备、智能电视都原生支持 较差,浏览器不原生支持,需要插件或转码

应用场景

  • 选择 HLS 的情况:
    • 主流互联网视频点播和直播(如 YouTube, Bilibili, Twitch)。
    • 需要覆盖最广泛的终端用户(通过浏览器、手机App、智能电视直接观看)。
    • 网络环境复杂多变,需要自适应码率来保证用户体验。
    • 对延迟不敏感(延迟在10-20秒可接受)。
  • 选择 RTSP 的情况:
    • 视频监控系统(IPCAM): 这是 RTSP 目前最主流的应用领域,需要低延迟查看实时画面。
    • 视频会议或视频聊天(如某些移动端应用): 极低的延迟是关键。
    • 专网或局域网内的流媒体应用,可以控制网络环境,避免防火墙问题。
    • 需要与旧有流媒体系统集成

发展趋势

  • HLS 是当今互联网公网传输的绝对主流,并且通过低延迟技术不断优化其短板。
  • RTSP 在特定领域(如安防、物联网)依然不可替代,但在公共互联网领域已被基于 HTTP 的协议(如 HLS 和 MPEG-DASH)所取代。
  • WebRTC作为另一个低延迟协议,在实时通信(如视频会议、在线教育)领域正挑战着 RTSP 的地位,因为它能直接在浏览器中运行。

七、电视迷视频下载实战

作为一个程序员以及一个爱刷剧的仔,怎么实现刷剧自由呢?电视迷网站上有很多好剧,不过可能存在因为下架的风险,以及中间会插入一些澳门菠菜网站的广告,那作为程序员的我,职业病就犯了,爬它。让我们在回顾一下爬虫的关键步骤:

1)网页分析

2)url提取和关键元素匹配

3)保存资源

网页分析是关键,此网站也是使用m3u8文件来保存视频的。

7.1 网页分析

https://dsmi.cc/tvb/XiaoAoJiangHu/yunbo-1-43.html

每一集视频都是yunbo-1-集数.html 的url链接,可以使用遍历的方式进行爬取,这个具体的网页内容分析:

  • yunbo-1-43.html 分析

从网页中获取视频链接,如下位置:

复制代码
<script>var vt={"id":"28","tid":"0","jid":"42","nid":"43","tit":"笑傲江湖(96版)国语","v_name":"tvb","uid":"https://vip.ffzy-online4.com/share/c0a3eab00393c89313e8109bb6504a68","cid":"yunbo","nuid":"","ncid":"","jtit":"第43集","njtit":"","mulu":"XiaoAoJiangHu","zxyj":"/tvb/XiaoAoJiangHu/yunbo-1-43.html","v_note":"43"};

</script>

其中uid 表示链接url,但不是具体的视频文件,是一个base_url。

复制代码
https://vip.ffzy-online4.com/share/c0a3eab00393c89313e8109bb6504a68
  • 获取m3u8

以下js脚本中定义m3u8文件url,是一个相对地址。

复制代码
<script type="text/javascript">
            var video_player= 'artplayer'
            var tracker_url = ''
            var signaler_url = ''
            var auto_play = ''
            var hosts = '';
            var redirecturl = "http://vip.okzybo.com";
            var videoid = "c0a3eab00393c89313e8109bb6504a68";

            var id = 'c0a3eab00393c89313e8109bb6504a68'
            var     l = ''
            var     r= ''
            var     t= '15'
            var     d= ''
            var     u= ''

            var main = "/20230224/10825_cf435d2c/index.m3u8?sign=30db3fb63fd9b8e8edc7d1c02785f9d2";
            var xml = "/20230224/10825_cf435d2c/index.xml?sign=30db3fb63fd9b8e8edc7d1c02785f9d2";
            var pic = "/20230224/10825_cf435d2c/1.jpg";
            var thumbnails = "/20230224/10825_cf435d2c/thumbnails.jpg";
        </script>

var main = "/20230224/10825_cf435d2c/index.m3u8?sign=30db3fb63fd9b8e8edc7d1c02785f9d2";

这里m3u8文件路径是一个相对路径,需要加上上数的base_url才是m3u8文件绝对路径。

https://vip.ffzy-online4.com/20230224/10825_cf435d2c/index.m3u8?sign=30db3fb63fd9b8e8edc7d1c02785f9d2

7.2 爬虫方案

1)使用idx++遍历方式,基于yunbo-1-xxx.htm找到每一集的url。

2)具体页面html分析,使用etree html选择器匹配找到对应的m3u8文件。

复制代码
<script>var vt={"id":"28","tid":"0","jid":"42","nid":"43","tit":"笑傲江湖(96版)国语","v_name":"tvb","uid":"https://vip.ffzy-online4.com/share/c0a3eab00393c89313e8109bb6504a68","cid":"yunbo","nuid":"","ncid":"","jtit":"第43集","njtit":"","mulu":"XiaoAoJiangHu","zxyj":"/tvb/XiaoAoJiangHu/yunbo-1-43.html","v_note":"43"};

3)var vt使用正则表达式匹配内容,然后转成json数组。

复制代码
ret = re.match(pattern, str)
注意使用非贪婪算法.*?
  • index.m3u8

拼接得出的m3u8文件路径:

https://vip.ffzy-online4.com/20230224/10825_cf435d2c/2000k/hls/mixed.m3u8

下载index.m3u8文件内容如下:

复制代码
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608
2000k/hls/mixed.m3u8

7.3 解析index.m3u8

mixed.m3u8中才保存的是具体的是ts链接。

复制代码
2000k/hls/mixed.m3u8

不用解析index.m3u8文件,直接把url中的index.m3u8替换为mixed.m3u8即可,然后mixed.m3u8文件。

  • 使用python下载http文件

    import urllib.request

    url = 'http://example.com/file.txt'
    save_path = 'path/to/save/file.txt'

    urllib.request.urlretrieve(url, save_path)
    print('文件已下载到', save_path)

方法2:

复制代码
import requests
url = 'http://example.com/file.txt'
save_path = 'path/to/save/file.txt'

response = requests.get(url)
with open(save_path, 'wb') as file:
    file.write(response.content)
print('文件已下载到', save_path)

7.4 解析mixed.m3u8

mixed.m3u8内容格式如下,其中的ts的url是没有索引的,所以下载后需要增加绝对路径地址。

复制代码
#EXTINF:1.520000,
0a8acd2744d000118.ts
#EXT-X-DISCONTINUITY
#EXTINF:6.666667,
0a8acd2744d0577670.ts
#EXTINF:3.333333,
0a8acd2744d0577671.ts
#EXTINF:3.333333,
0a8acd2744d0577672.ts
#EXTINF:5.366667,
0a8acd2744d0577673.ts
#EXTINF:1.300000,
0a8acd2744d0577674.ts
#EXT-X-DISCONTINUITY
#EXTINF:6.800000,
0a8acd2744d000119.ts
#EXTINF:1.800000,
0a8acd2744d000120.ts
#EXTINF:5.840000,
0a8acd2744d000121.ts

添加后的ts路径:

复制代码
https://vip.ffzy-online4.com/20230224/10825_cf435d2c/2000k/hls/0a8acd2744d000006.ts

7.5 去菠菜广告视频

视频中有菠菜广告视频,需要分析ts将其删除。

ts分析

复制代码
78e8d4b1bb1000115.ts
78e8d4b1bb1000116.ts
78e8d4b1bb1000117.ts
78e8d4b1bb1000118.ts
78e8d4b1bb10359685.ts
78e8d4b1bb10359686.ts
78e8d4b1bb10359687.ts
78e8d4b1bb10359688.ts
78e8d4b1bb10359689.ts

分析ts文件,正常视频文件名都是递增连续的,但是中间有一些ts文件名不是连续的,且值超过了一定范围,确认这些确实是广告视频,从ts中删掉即可。

tips:python编码技巧:re.S匹配换行符,支持多行匹配。

复制代码
re.findall(r"a(\d+)b.+a(\d+)b", str, re.S)
#s输出[('23', '34')]

完整代码如下:

复制代码
# -*-coding:utf8-*-
import requests
import lxml
from lxml import etree
import os
import base64
import re
import time
import socket
import urllib

#timeout = 20  
#socket.setdefaulttimeout(timeout)

video_name="XiaoAoJiangHu"


http_headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.41",
}

def parse_m3u8(idx, url):
    #cmd = "ffmpeg -i %s -c copy %s_%d.mp4" % (url, video_name, idx)
    #os.system(cmd)
    print(url)
    base_url = os.path.dirname(url)
    mixed_url = base_url + "/2000k/hls/mixed.m3u8"
    print(mixed_url)
    page = requests.get(mixed_url, headers=http_headers)
    page.encoding = "utf-8"
    mix_m3u8_content = str(page.content, encoding='utf-8')
    #print("===========" + mix_m3u8_content)
    #len_cnt = [0 for _ in range(100)] 
    maxlen = 0;
    ts_list = re.findall(".*?\.ts", mix_m3u8_content)
    for ts in ts_list:
         if (maxlen < len(ts)):
             maxlen = len(ts)
    
    print("max ts len:%d" % maxlen)
    lajits_list = []
    for ts in ts_list:
         if (maxlen == len(ts)):
             lajits_list.append(ts)

    print("lajits:")
    for lajits in lajits_list:
        print(lajits)

    ts_list = re.findall("#EXTINF:.*?\.ts", mix_m3u8_content, re.S)
    for ts in ts_list:
        for lajits in lajits_list:
            if lajits in ts:
                print("lajits:")
                print(ts)
                mix_m3u8_content = mix_m3u8_content.replace(ts, "")
    with open("mixd.m3u8", "w") as mixfile:
        mixfile.write(mix_m3u8_content)

    
    #save_path = "mixed.m3u8"
    #urllib.request.urlretrieve(mixed_url, save_path)
    #print('文件已下载到', save_path)


def parseVideoPage(idx, url):
    page = requests.get(url, headers=http_headers)
    page.encoding = "utf-8"
    html = page.text

    #print(html)

    selector = etree.HTML(html)

    script = selector.xpath('//script/text()')

    print("script:", script[0])

    ret = re.findall("var main = (.*?);", script[0])
    print("ret=", ret[0])
    page.close()

    m3u8_url = ret[0]

    # TODO : fix me
    m3u8_url = m3u8_url.replace('\"', '')
    parse_m3u8(idx, "https://vip.ffzy-online4.com/" + m3u8_url)
    return


def parseHomePage(idx, url):
    page = requests.get(url, headers=http_headers)
    page.encoding = "utf-8"
    html = page.text

    #print(html)

    selector = etree.HTML(html)

    script = selector.xpath('//script/text()')

    print("script:", script[0])

    ret = re.findall("\"uid\":(.*?),", script[0])
    print("ret=", ret[0])
    page.close()

    video_url = ret[0]
    video_url = video_url.replace('"', '')
    print("video_url=", video_url)
    parseVideoPage(idx, video_url)
    return

if __name__ == '__main__':

    for idx in range(1,44):
        parseHomePage(idx, "https://dsmi.cc/tvb/XiaoAoJiangHu/yunbo-1-%d.html" % idx)
    #parseHomePage("https://dsmi.cc/tvb/XiaoAoJiangHu/yunbo-1-43.html")
    #parseVideoPage("https://vip.ffzy-online4.com/share/c0a3eab00393c89313e8109bb6504a68")
    #parse_m3u8("https://vip.ffzy-online4.com/20230224/10825_cf435d2c/index.m3u8?sign=30db3fb63fd9b8e8edc7d1c02785f9d2")

八、参考链接

m3u8文件介绍:

https://www.cnblogs.com/renhui/p/10351870.html

https://www.cnblogs.com/mq0036/p/14961793.html

https://zhuanlan.zhihu.com/p/162947124

https://www.makeuseof.com/what-is-an-m3u8-file-how-to-open-it/

hls协议介绍:

https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-23

https://www.cnblogs.com/heluan/p/8944319.html

ts相关链接:

https://zhuanlan.zhihu.com/p/520985863

https://zhuanlan.zhihu.com/p/608579756

H.222.0 : Information technology - Generic coding of moving pictures and associated audio information: Systems

m3u8文件下载:

https://blog.csdn.net/chy_18883701161/article/details/118884565

相关推荐
音视频牛哥3 小时前
从 SmartMediaKit 设计探讨音视频工程师的面试与能力评估框架
程序人生·职场和发展·音视频·rtsp播放器·rtmp播放器·音视频工程师面试·音视频程序员面试题
18538162800航4 小时前
短视频矩阵系统搭建指南:源码部署与全流程解析
线性代数·矩阵·音视频
美摄科技5 小时前
AR短视频SDK,打造差异化竞争壁垒
ar·音视频
sunly_5 小时前
Flutter:视频预览功能
javascript·flutter·音视频
热爱编程的小白白5 小时前
IPIDEA海外代理助力-Youtube视频AI领域选题数据获取实践
人工智能·音视频
闲人编程7 小时前
从零开发一个简单的Web爬虫(使用Requests和BeautifulSoup)
前端·爬虫·beautifulsoup·bs4·web·request·codecapsule
B站计算机毕业设计之家8 小时前
大数据python招聘数据分析预测系统 招聘数据平台 +爬虫+可视化 +django框架+vue框架 大数据技术✅
大数据·爬虫·python·机器学习·数据挖掘·数据分析
疏狂难除10 小时前
spiderdemo第22题与webassembly的跨域
开发语言·javascript·爬虫·rust·wasm·mitmproxy
骄傲的心别枯萎11 小时前
RV1126 NO.40:OPENCV图形计算面积、弧长API讲解
人工智能·opencv·计算机视觉·音视频·rv1126