#multimedia #video-processing #hls #ffmpeg #multimedia-encoding #encoding #streaming

hlskit

HlsKit provides strong HLS video conversion features backed by ffmpeg. Prepare your mp4 files for streaming

2 releases

new 0.1.2 Apr 10, 2025
0.1.0 Apr 9, 2025

#120 in Video

Download history 154/week @ 2025-04-04

156 downloads per month

LGPL-3.0-or-later

19KB
282 lines

HlsKit

HlsKit is a high-performance Rust library for transcoding MP4 videos into HLS (HTTP Live Streaming) streams with adaptive bitrate support and multiple resolutions. It leverages ffmpeg under the hood and will soon support gstreamer as a pluggable backend.

Whether you're building a video streaming platform or need offline transcoding tools for video delivery, HlsKit provides an ergonomic, async-first API to handle the full conversion process: segmenting videos, creating resolution-specific playlists, and generating a master .m3u8 playlist for adaptive streaming.

Wanna contribute? Check CONTRIBUTING.md


๐ŸŒ How It Works

flowchart TD
    A[Input MP4 Bytes] --> B{For Each Resolution}
    B -->|1080p| C1[Spawn ffmpeg Task]
    B -->|720p| C2[Spawn ffmpeg Task]
    B -->|480p| C3[Spawn ffmpeg Task]
    C1 & C2 & C3 --> D[Generate .ts Segments & .m3u8 Playlists]
    D --> E[Generate Master Playlist - master.m3u8 file]
    E --> F[Return HlsVideo Struct]

โœจ Features

  • โœ… Convert MP4 videos to HLS format with multiple resolutions.
  • โœ… Adaptive bitrate support via master playlist.
  • โœ… Async-native using tokio.
  • โœ… Configurable CRF-based encoding and speed presets.
  • ๐Ÿ”œ Pluggable backends: GStreamer coming soon.

๐Ÿš€ Usage Example

use std::{env, fs::File, io::Read};
use hlskit::{
    models::hls_video_processing_settings::{FfmpegVideoProcessingPreset, HlsVideoProcessingSettings},
    process_video,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut buf = Vec::new();
    File::open("src/sample.mp4")?.read_to_end(&mut buf)?;

    let result = process_video(
        buf,
        vec![
            HlsVideoProcessingSettings {
                resolution: (1920, 1080),
                constant_rate_factor: 28,
                preset: FfmpegVideoProcessingPreset::Fast,
            },
            HlsVideoProcessingSettings {
                resolution: (1280, 720),
                constant_rate_factor: 28,
                preset: FfmpegVideoProcessingPreset::Fast,
            },
            HlsVideoProcessingSettings {
                resolution: (854, 480),
                constant_rate_factor: 28,
                preset: FfmpegVideoProcessingPreset::Fast,
            },
        ],
    )
    .await?;

    println!("Master playlist:\n{}", String::from_utf8_lossy(&result.master_m3u8_data));
    Ok(())
}

๐ŸŒ Web Server Integration Example + S3 Upload

You can integrate HlsKit into an axum web server and upload results to Amazon S3:

# Cargo.toml
[dependencies]
hlskit = { git = "https://github.com/like-engels/hlskit-rs" }
axum = "0.7"
tokio = { version = "1", features = ["full"] }
aws-sdk-s3 = "0.30"
mime = "0.3"
uuid = { version = "1", features = ["v4"] }
use axum::{
    extract::Multipart,
    response::IntoResponse,
    routing::post,
    Router,
};
use aws_sdk_s3::Client as S3Client;
use hlskit::{
    models::hls_video_processing_settings::{FfmpegVideoProcessingPreset, HlsVideoProcessingSettings},
    process_video,
};
use std::net::SocketAddr;
use uuid::Uuid;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/upload", post(upload));
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    println!("Server running at http://{}", addr);
    axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}

async fn upload(mut multipart: Multipart) -> impl IntoResponse {
    let mut video_bytes = Vec::new();

    while let Some(field) = multipart.next_field().await.unwrap() {
        if field.name() == Some("video") {
            video_bytes = field.bytes().await.unwrap().to_vec();
            break;
        }
    }

    let profiles = vec![
        HlsVideoProcessingSettings {
            resolution: (1920, 1080),
            constant_rate_factor: 28,
            preset: FfmpegVideoProcessingPreset::Fast,
        },
        HlsVideoProcessingSettings {
            resolution: (1280, 720),
            constant_rate_factor: 28,
            preset: FfmpegVideoProcessingPreset::Fast,
        },
    ];

    match process_video(video_bytes, profiles).await {
        Ok(hls_video) => {
            let s3 = S3Client::new(&aws_config::load_from_env().await);
            let uuid = Uuid::new_v4().to_string();
            let bucket = "my-hls-videos";

            s3.put_object()
                .bucket(bucket)
                .key(format!("{}/master.m3u8", uuid))
                .body(hls_video.master_m3u8_data.into())
                .send()
                .await
                .unwrap();

            for resolution in hls_video.resolutions {
                s3.put_object()
                    .bucket(bucket)
                    .key(format!("{}/{}", uuid, resolution.playlist_name))
                    .body(resolution.playlist_data.into())
                    .send()
                    .await
                    .unwrap();

                for segment in resolution.segments {
                    s3.put_object()
                        .bucket(bucket)
                        .key(format!("{}/{}", uuid, segment.segment_name))
                        .body(segment.segment_data.into())
                        .send()
                        .await
                        .unwrap();
                }
            }

            format!("HLS stream uploaded to s3://{}/{}", bucket, uuid)
        }
        Err(e) => format!("Processing failed: {:?}", e),
    }
}

โœ… Requires AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_REGION to be set in the environment.


๐Ÿ“ฆ Installation

[dependencies]
hlskit = { git = "https://github.com/like-engels/hlskit-rs" }

๐Ÿ“Œ Requirements

  • Rust 1.70+
  • FFmpeg must be installed in your system and available in $PATH

๐Ÿ›ฃ๏ธ Roadmap

  • ๐Ÿ”„ GStreamer backend
  • ๐Ÿ“ฆ Crates.io publish
  • ๐Ÿงช Comprehensive test coverage
  • ๐Ÿ’ก Custom audio profiles & watermarking
  • ๐Ÿ“„ Better documentation

๐Ÿชช License

HlsKit is licensed under LGPLv3. By modifying or distributing it (e.g., via forks or extensions), you agree to the HlsKit Contributor License Agreement (CLA), which ensures our ecosystem thrives.

The 'HlsKit' name and logo are trademarks of Engels Tercero. Use in forks or derivatives requires written permission.

Dependencies

~7โ€“16MB
~228K SLoC