2 releases
new 0.1.2 | Apr 10, 2025 |
---|---|
0.1.0 | Apr 9, 2025 |
#120 in Video
156 downloads per month
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
, andAWS_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