# m3u8-rs ![crates.io](https://img.shields.io/crates/v/m3u8-rs.svg) A Rust library for parsing m3u8 playlists (HTTP Live Streaming) [link](https://tools.ietf.org/html/draft-pantos-http-live-streaming-19). Uses the [`nom` library](https://github.com/Geal/nom) for all of the parsing. # Installation To use this library, add the following dependency to `Cargo.toml`: ```toml [dependencies] m3u8-rs = "1.0.6" ``` And add the crate to `lib.rs` ```rust extern crate m3u8_rs; ``` Also available on [crates.io](https://crates.io/crates/m3u8-rs) # Documentation Available [here](https://rutgersc.github.io/doc/m3u8_rs/index.html) # Examples A simple example of parsing a playlist: ```rust use m3u8_rs::playlist::Playlist; use std::io::Read; let mut file = std::fs::File::open("playlist.m3u8").unwrap(); let mut bytes: Vec = Vec::new(); file.read_to_end(&mut bytes).unwrap(); let parsed = m3u8_rs::parse_playlist_res(&bytes); match parsed { Ok(Playlist::MasterPlaylist(pl)) => println!("Master playlist:\n{}", pl), Ok(Playlist::MediaPlaylist(pl)) => println!("Media playlist:\n{}", pl), Err(e) => println!("Error: {:?}", e) } ``` In the example above, `parse_playlist_res(&bytes)` returns a `Result`. It uses the output of `parse_playlist(&bytes)` behind the scenes and just converts the `IResult` to a `Result`. Here is an example of using the `parse_playlist(&bytes)` with `IResult` directly: ```rust use m3u8_rs::playlist::Playlist; use std::io::Read; use nom::IResult; let mut file = std::fs::File::open("playlist.m3u8").unwrap(); let mut bytes: Vec = Vec::new(); file.read_to_end(&mut bytes).unwrap(); let parsed = m3u8_rs::parse_playlist(&bytes); match parsed { IResult::Ok((i, Playlist::MasterPlaylist(pl))) => println!("Master playlist:\n{}", pl), IResult::Ok((i, Playlist::MediaPlaylist(pl))) => println!("Media playlist:\n{}", pl), IResult::Error(e) => panic!("Parsing error: \n{}", e), IResult::Incomplete(e) => panic!("Parsing error: \n{:?}", e), } ``` Currently, the parser will succeed even if REQUIRED attributes/tags are missing from a playlist (such as the `#EXT-X-VERSION` tag). The option to abort parsing when attributes/tags are missing may be something to add later on. # Structure Summary All the details about the structs are taken from https://tools.ietf.org/html/draft-pantos-http-live-streaming-19. ```rust // Short summary of the important structs in playlist.rs: // pub enum Playlist { MasterPlaylist(MasterPlaylist), MediaPlaylist(MediaPlaylist), } pub struct MasterPlaylist { pub version: usize, pub variants: Vec, pub session_data: Option, pub session_key: Option, pub start: Option, pub independent_segments: bool, pub alternatives: Vec, pub unknown_tags: Vec, } pub struct MediaPlaylist { pub version: usize, pub target_duration: f32, pub media_sequence: i32, pub segments: Vec, pub discontinuity_sequence: i32, pub end_list: bool, pub playlist_type: MediaPlaylistType, pub i_frames_only: bool, pub start: Option, pub independent_segments: bool, } pub struct VariantStream { pub is_i_frame: bool, pub uri: String, pub bandwidth: String, pub average_bandwidth: Option, pub codecs: String, pub resolution: Option, pub frame_rate: Option, pub audio: Option, pub video: Option, pub subtitles: Option, pub closed_captions: Option, pub alternatives: Vec, } pub struct MediaSegment { pub uri: String, pub duration: f32, pub title: Option, pub byte_range: Option, pub discontinuity: bool, pub key: Option, pub map: Option, pub program_date_time: Option, pub daterange: Option, pub unknown_tags: Vec, } ```