4个版本
0.1.2 | 2022年10月14日 |
---|---|
0.1.1 | 2022年10月13日 |
198 在 多媒体
40KB
264 行
清单修改器
清单修改器 是一个正在开发中的项目,用于修改视频清单。
为什么?视频有点复杂。由于帧率、比特率或其他可能影响播放的标签,某些清单可能在某些设备上无法运行。
上面的图片是一个完美的例子,描述了一个常见问题:一些设备无法播放60fps的视频。为了解决这种情况,我们可以在向用户发送之前使用 manifest-modifier
重新编写清单。
使用此项目有两种方式,要么作为库,要么作为服务器。此项目分为两个crate: manifest-filter
和 manifest-server
。 manifest-server
是基于 axum 和 m3u8-rs 构建的服务器。它可以在不要求有高级Rust编程语言知识的情况下使用。
manifest-filter
是 manifest-server
背后的Rust代码。如果您运行自己的服务器并且无法使用 manifest-server
,无需担心,您可以通过直接调用Rust代码来使用相同的功能
use manifest_filter::Master;
use std::io::Read;
let mut file = std::fs::File::open("manifests/master.m3u8").unwrap();
let mut content: Vec<u8> = Vec::new();
file.read_to_end(&mut content).unwrap();
let (_, master_playlist) = m3u8_rs::parse_master_playlist(&content).unwrap();
let mut master = Master {
playlist: master_playlist,
};
master.filter_fps(Some(30.0));
结果应该是这样的
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aach-96",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-STREAM-INF:BANDWIDTH=600000,AVERAGE-BANDWIDTH=600000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=384x216,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=249984.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,AVERAGE-BANDWIDTH=800000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=768x432,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=1320960.m3u8
安装
manifest-server
的二进制文件是 manifest_server
您必须拥有 cargo
才能安装清单服务器
$ cargo install manifest-server`
目前还没有其他安装服务器的方法。
用法
为了使服务器正常工作,您需要导出一个变量 LISTEN_ADDRESS
$ LISTEN_ADDRESS=127.0.0.1:3000 manifest_server`
特性
主播放列表
带宽 - 根据最小和最大值过滤变体。
请求
curl --request POST \
--url 'https://127.0.0.1:3000/master?min_bitrate=800000&max_bitrate=2000000' \
--header 'content-type: text/html; charset=UTF-8' \
--header 'user-agent: vscode-restclient' \
--data '< ../manifest-filter/manifests/master.m3u8'
响应
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aach-96",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-STREAM-INF:BANDWIDTH=800000,AVERAGE-BANDWIDTH=800000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=768x432,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=1320960.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1500000,AVERAGE-BANDWIDTH=1500000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=3092992.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,AVERAGE-BANDWIDTH=2000000,CODECS="mp4a.40.5,avc1.640029",RESOLUTION=1920x1080,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=4686976.m3u8
原始播放列表
如您所见,原始播放列表略有不同
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aach-96",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-STREAM-INF:BANDWIDTH=600000,AVERAGE-BANDWIDTH=600000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=384x216,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=249984.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,AVERAGE-BANDWIDTH=800000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=768x432,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=1320960.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1500000,AVERAGE-BANDWIDTH=1500000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=3092992.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,AVERAGE-BANDWIDTH=2000000,CODECS="mp4a.40.5,avc1.640029",RESOLUTION=1920x1080,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=4686976.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=37000,CODECS="avc1.64001F",RESOLUTION=384x216,URI="keyframes/variant-video=249984.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=193000,CODECS="avc1.64001F",RESOLUTION=768x432,URI="keyframes/variant-video=1320960.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=296000,CODECS="avc1.64001F",RESOLUTION=1280x720,URI="keyframes/variant-video=2029952.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=684000,CODECS="avc1.640029",RESOLUTION=1920x1080,URI="keyframes/variant-video=4686976.m3u8"
帧率 - 根据预定义的 fps 过滤变体
请求
curl --request POST \
--url 'https://127.0.0.1:3000/master?rate=60' \
--header 'content-type: text/html; charset=UTF-8' \
--header 'user-agent: vscode-restclient' \
--data '< ../manifest-filter/manifests/master.m3u8'
响应
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aach-96",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-STREAM-INF:BANDWIDTH=1500000,AVERAGE-BANDWIDTH=1500000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=3092992.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,AVERAGE-BANDWIDTH=2000000,CODECS="mp4a.40.5,avc1.640029",RESOLUTION=1920x1080,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=4686976.m3u8
原始播放列表
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aach-96",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-STREAM-INF:BANDWIDTH=600000,AVERAGE-BANDWIDTH=600000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=384x216,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=249984.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,AVERAGE-BANDWIDTH=800000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=768x432,FRAME-RATE=30,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=1320960.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1500000,AVERAGE-BANDWIDTH=1500000,CODECS="mp4a.40.5,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=3092992.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,AVERAGE-BANDWIDTH=2000000,CODECS="mp4a.40.5,avc1.640029",RESOLUTION=1920x1080,FRAME-RATE=60,AUDIO="audio-aach-96",CLOSED-CAPTIONS=NONE
variant-audio_1=96000-video=4686976.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=37000,CODECS="avc1.64001F",RESOLUTION=384x216,URI="keyframes/variant-video=249984.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=193000,CODECS="avc1.64001F",RESOLUTION=768x432,URI="keyframes/variant-video=1320960.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=296000,CODECS="avc1.64001F",RESOLUTION=1280x720,URI="keyframes/variant-video=2029952.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=684000,CODECS="avc1.640029",RESOLUTION=1920x1080,URI="keyframes/variant-video=4686976.m3u8"
媒体播放列表
DVR - 根据持续时间(秒)删除段(向后)
curl --request POST \
--url 'https://127.0.0.1:3000/media?dvr=15' \
--header 'content-type: text/html; charset=UTF-8' \
--header 'user-agent: vscode-restclient' \
--data '< ../manifest-filter/manifests/media.m3u8'
响应
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:320035373
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035703.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035702.ts
#EXT-X-PROGRAM-DATE-TIME:2020-09-15T14:01:39.133333+00:00
#EXT-X-CUE-IN
#EXTINF:5.8666, no desc
variant-audio_1=96000-video=249984-320035701.ts
原始播放列表
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:320035356
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:8
#EXT-X-PROGRAM-DATE-TIME:2020-09-15T13:32:55Z
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035684.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035685.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035686.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035687.ts
#EXTINF:4.1333, no desc
variant-audio_1=96000-video=249984-320035688.ts
#EXT-X-DATERANGE:ID="4026531847",START-DATE="2020-09-15T14:00:39.133333Z",PLANNED-DURATION=60,SCTE35-OUT=0xFC3025000000000BB800FFF01405F00000077FEFFE0AF311F0FE005265C0000101010000817C918E
#EXT-X-CUE-OUT:60
#EXT-X-PROGRAM-DATE-TIME:2020-09-15T14:00:39.133333Z
#EXTINF:5.8666, no desc
variant-audio_1=96000-video=249984-320035689.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035690.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035691.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035692.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035693.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035694.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035695.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035696.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035697.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035698.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035699.ts
#EXTINF:4.1333, no desc
variant-audio_1=96000-video=249984-320035700.ts
#EXT-X-CUE-IN
#EXT-X-PROGRAM-DATE-TIME:2020-09-15T14:01:39.133333Z
#EXTINF:5.8666, no desc
variant-audio_1=96000-video=249984-320035701.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035702.ts
#EXTINF:5, no desc
variant-audio_1=96000-video=249984-320035703.ts
测试
cargo test
代码审查
cargo clippy
依赖项
~13–25MB
~337K SLoC