#live-streaming #m3u8 #streaming-parser #hls #playlist #media #http

m3u8-rs

A library for parsing m3u8 files (Apple's HTTP Live Streaming (HLS) protocol)

20 stable releases (5 major)

6.0.0 Feb 14, 2024
5.0.5 Dec 5, 2023
5.0.4 May 8, 2023
5.0.3 Dec 2, 2022
1.0.1 Jun 3, 2016

#21 in Video

Download history 3335/week @ 2024-09-09 4092/week @ 2024-09-16 4578/week @ 2024-09-23 4135/week @ 2024-09-30 3802/week @ 2024-10-07 5608/week @ 2024-10-14 5281/week @ 2024-10-21 5901/week @ 2024-10-28 5186/week @ 2024-11-04 5153/week @ 2024-11-11 5481/week @ 2024-11-18 5243/week @ 2024-11-25 5354/week @ 2024-12-02 5918/week @ 2024-12-09 5064/week @ 2024-12-16 2323/week @ 2024-12-23

18,949 downloads per month
Used in 27 crates (18 directly)

MIT license

80KB
2K SLoC

m3u8-rs

crates.io API

A Rust library for parsing m3u8 playlists (HTTP Live Streaming) link. Uses the nom library for all of the parsing.

Examples

Examples can be found in the examples folder.


lib.rs:

A library to parse m3u8 playlists HTTP Live Streaming.

Examples

Parsing a playlist and let the parser figure out if it's a media or master playlist.

use m3u8_rs::Playlist;
use nom::IResult;
use std::io::Read;

let mut file = std::fs::File::open("playlist.m3u8").unwrap();
let mut bytes: Vec<u8> = Vec::new();
file.read_to_end(&mut bytes).unwrap();

match m3u8_rs::parse_playlist(&bytes) {
    Result::Ok((i, Playlist::MasterPlaylist(pl))) => println!("Master playlist:\n{:?}", pl),
    Result::Ok((i, Playlist::MediaPlaylist(pl))) => println!("Media playlist:\n{:?}", pl),
    Result::Err(e) =>  panic!("Parsing error: \n{}", e),
}

Parsing a master playlist directly

use std::io::Read;
use nom::IResult;

let mut file = std::fs::File::open("masterplaylist.m3u8").unwrap();
let mut bytes: Vec<u8> = Vec::new();
file.read_to_end(&mut bytes).unwrap();

if let Result::Ok((_, pl)) = m3u8_rs::parse_master_playlist(&bytes) {
    println!("{:?}", pl);
}

Creating a playlist and writing it back to a vec/file

use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment};

let playlist = MediaPlaylist {
    version: Some(6),
    target_duration: 3,
    media_sequence: 338559,
    discontinuity_sequence: 1234,
    end_list: true,
    playlist_type: Some(MediaPlaylistType::Vod),
    segments: vec![
        MediaSegment {
            uri: "20140311T113819-01-338559live.ts".into(),
            duration: 2.002,
            title: Some("title".into()),
            ..Default::default()
        },
    ],
    ..Default::default()
};

//let mut v: Vec<u8> = Vec::new();
//playlist.write_to(&mut v).unwrap();

//let mut file = std::fs::File::open("playlist.m3u8").unwrap();
//playlist.write_to(&mut file).unwrap();

Controlling the output precision for floats, such as #EXTINF (default is unset)

use std::sync::atomic::Ordering;
use m3u8_rs::{WRITE_OPT_FLOAT_PRECISION, MediaPlaylist, MediaSegment};

WRITE_OPT_FLOAT_PRECISION.store(5, Ordering::Relaxed);

let playlist = MediaPlaylist {
    target_duration: 3,
    segments: vec![
        MediaSegment {
            duration: 2.9,
            title: Some("title".into()),
            ..Default::default()
        },
    ],
    ..Default::default()
};

let mut v: Vec<u8> = Vec::new();

playlist.write_to(&mut v).unwrap();
let m3u8_str: &str = std::str::from_utf8(&v).unwrap();
assert!(m3u8_str.contains("#EXTINF:2.90000,title"));

Dependencies

~1–1.4MB
~22K SLoC