{"id":27165768,"url":"https://github.com/like-engels/hlskit-rs","last_synced_at":"2025-07-24T12:08:11.973Z","repository":{"id":286924940,"uuid":"962950374","full_name":"like-engels/hlskit-rs","owner":"like-engels","description":"HlsKit provides strong HLS video conversion features backed by ffmpeg. Prepare your mp4 files for streaming.","archived":false,"fork":false,"pushed_at":"2025-07-03T04:28:20.000Z","size":72497,"stargazers_count":8,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-03T05:25:21.076Z","etag":null,"topics":["cloudfront","ffmpeg","ffmpeg-rust","gstreamer","gstreamer-rust","hls","hls-live-streaming","mp4","multimedia","rust","transcoding","video-compressing","video-compressor","video-processing","video-streaming"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/like-engels.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-08T23:34:23.000Z","updated_at":"2025-06-28T18:24:00.000Z","dependencies_parsed_at":"2025-07-03T05:32:16.614Z","dependency_job_id":null,"html_url":"https://github.com/like-engels/hlskit-rs","commit_stats":null,"previous_names":["like-engels/hlskit-rs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/like-engels/hlskit-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-engels%2Fhlskit-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-engels%2Fhlskit-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-engels%2Fhlskit-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-engels%2Fhlskit-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/like-engels","download_url":"https://codeload.github.com/like-engels/hlskit-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-engels%2Fhlskit-rs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263269455,"owners_count":23440190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudfront","ffmpeg","ffmpeg-rust","gstreamer","gstreamer-rust","hls","hls-live-streaming","mp4","multimedia","rust","transcoding","video-compressing","video-compressor","video-processing","video-streaming"],"created_at":"2025-04-09T03:20:44.593Z","updated_at":"2025-07-03T15:37:48.284Z","avatar_url":"https://github.com/like-engels.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HlsKit\n\n**HlsKit** is a high-performance Rust library for transcoding MP4 videos into [HLS (HTTP Live Streaming)](https://developer.apple.com/streaming/) streams with adaptive bitrate support and multiple resolutions. It leverages `ffmpeg` under the hood and will soon support `gstreamer` as a pluggable backend.\n\nWhether 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.\n\nWanna contribute? Check [CONTRIBUTING.md](./CONTRIBUTING.md)\n\n---\n\n## HlsKit 0.2.0 Released!!!\nHlsKit now supports AES-128 HLS segment encryption by providing a key file and a custom initialization vector (IV).\n\nTo encrypt HLS segments first create a key with OpenSSL with the following command:\n\n```bash\nopenssl rand 16 \u003e hls.key\n```\n\nNow, instead of calling process_video(), you should call process_video_with_encrypted_segments()\nThen just pass the following additional parameters:\n\n- `encryption_key_url`: The public accessible URL to the key file.\n- `encryption_key_path`: Path to the key file in the server.\n- `iv`: Initialization vector for encryption (optional).\n\n### Notes\n\nThe encryption key must be uploaded somewhere accessible by video players, we recommend using a secure storage service or a key server. The key also must be stored in the server where HlsKit is being used to transcode videos.\n\nHlsKit uses `encryption_key_path` to locate the key file in the server and encrypt HLS Segments, and uses `encryption_key_url` to set the `base_url` property in m3u8 playlists, allowing video players to retrieve the encryption key to read the segments, any security measures should be taken to protect the key file from unauthorized access.\n\nUsing encrypted HLS segments provides an additional layer of security, making it more difficult for unauthorized users to access the video content but it is not a drop-in replacement for DRM systems. It is recommended to use encrypted HLS segments in conjunction with DRM systems for maximum security.\n---\n\n## 🌐 How It Works\n\n```mermaid\nflowchart TD\n    A[Input MP4 Bytes] --\u003e B{For Each Resolution}\n    B --\u003e|1080p| C1[Spawn ffmpeg Task]\n    B --\u003e|720p| C2[Spawn ffmpeg Task]\n    B --\u003e|480p| C3[Spawn ffmpeg Task]\n    C1 \u0026 C2 \u0026 C3 --\u003e D[Generate .ts Segments \u0026 .m3u8 Playlists]\n    D --\u003e E[Generate Master Playlist - master.m3u8 file]\n    E --\u003e F[Return HlsVideo Struct]\n```\n\n---\n\n## ✨ Features\n\n- ✅ Convert MP4 videos to HLS format with multiple resolutions.\n- ✅ Adaptive bitrate support via master playlist.\n- ✅ Async-native using `tokio`.\n- ✅ Configurable CRF-based encoding and speed presets.\n- 🔜 Pluggable backends: GStreamer coming soon.\n\n---\n\n## 🚀 Usage Example\n\n```rust\nuse std::{env, fs::File, io::Read};\nuse hlskit::{\n    models::hls_video_processing_settings::{FfmpegVideoProcessingPreset, HlsVideoProcessingSettings},\n    process_video,\n};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut buf = Vec::new();\n    File::open(\"src/sample.mp4\")?.read_to_end(\u0026mut buf)?;\n\n    let result = process_video(\n        buf,\n        vec![\n            HlsVideoProcessingSettings::new(\n                (1920, 1080),\n                28,\n                None, // no custom audio code - defaulting to AAC\n                None, // no custom audio bitrate\n                FfmpegVideoProcessingPreset::Fast,\n            ),\n            HlsVideoProcessingSettings::new(\n                (1280, 720),\n                28,\n                None, // no custom audio code - defaulting to AAC\n                None, // no custom audio bitrate\n                FfmpegVideoProcessingPreset::Fast,\n            ),\n            HlsVideoProcessingSettings::new(\n                (854, 480),\n                28,\n                None, // no custom audio code - defaulting to AAC\n                None, // no custom audio bitrate\n                FfmpegVideoProcessingPreset::Fast,\n            ),\n        ],\n    )\n    .await?;\n\n    println!(\"Master playlist:\\n{}\", String::from_utf8_lossy(\u0026result.master_m3u8_data));\n    Ok(())\n}\n```\n\n---\n\n## 🌍 Web Server Integration Example + S3 Upload\n\nYou can integrate **HlsKit** into an `axum` web server and upload results to Amazon S3:\n\n```toml\n# Cargo.toml\n[dependencies]\nhlskit = { git = \"https://github.com/like-engels/hlskit-rs\" }\naxum = \"0.7\"\ntokio = { version = \"1\", features = [\"full\"] }\naws-sdk-s3 = \"0.30\"\nmime = \"0.3\"\nuuid = { version = \"1\", features = [\"v4\"] }\n```\n\n```rust\nuse axum::{\n    extract::Multipart,\n    response::IntoResponse,\n    routing::post,\n    Router,\n};\nuse aws_sdk_s3::Client as S3Client;\nuse hlskit::{\n    models::hls_video_processing_settings::{FfmpegVideoProcessingPreset, HlsVideoProcessingSettings},\n    process_video,\n};\nuse std::net::SocketAddr;\nuse uuid::Uuid;\n\n#[tokio::main]\nasync fn main() {\n    let app = Router::new().route(\"/upload\", post(upload));\n    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));\n    println!(\"Server running at http://{}\", addr);\n    axum::Server::bind(\u0026addr).serve(app.into_make_service()).await.unwrap();\n}\n\nasync fn upload(mut multipart: Multipart) -\u003e impl IntoResponse {\n    let mut video_bytes = Vec::new();\n\n    while let Some(field) = multipart.next_field().await.unwrap() {\n        if field.name() == Some(\"video\") {\n            video_bytes = field.bytes().await.unwrap().to_vec();\n            break;\n        }\n    }\n\n    let profiles = vec![\n        HlsVideoProcessingSettings {\n            resolution: (1920, 1080),\n            constant_rate_factor: 28,\n            preset: FfmpegVideoProcessingPreset::Fast,\n        },\n        HlsVideoProcessingSettings {\n            resolution: (1280, 720),\n            constant_rate_factor: 28,\n            preset: FfmpegVideoProcessingPreset::Fast,\n        },\n    ];\n\n    match process_video(video_bytes, profiles).await {\n        Ok(hls_video) =\u003e {\n            let s3 = S3Client::new(\u0026aws_config::load_from_env().await);\n            let uuid = Uuid::new_v4().to_string();\n            let bucket = \"my-hls-videos\";\n\n            s3.put_object()\n                .bucket(bucket)\n                .key(format!(\"{}/master.m3u8\", uuid))\n                .body(hls_video.master_m3u8_data.into())\n                .send()\n                .await\n                .unwrap();\n\n            for resolution in hls_video.resolutions {\n                s3.put_object()\n                    .bucket(bucket)\n                    .key(format!(\"{}/{}\", uuid, resolution.playlist_name))\n                    .body(resolution.playlist_data.into())\n                    .send()\n                    .await\n                    .unwrap();\n\n                for segment in resolution.segments {\n                    s3.put_object()\n                        .bucket(bucket)\n                        .key(format!(\"{}/{}\", uuid, segment.segment_name))\n                        .body(segment.segment_data.into())\n                        .send()\n                        .await\n                        .unwrap();\n                }\n            }\n\n            format!(\"HLS stream uploaded to s3://{}/{}\", bucket, uuid)\n        }\n        Err(e) =\u003e format!(\"Processing failed: {:?}\", e),\n    }\n}\n```\n\n\u003e ✅ Requires `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_REGION` to be set in the environment.\n\n---\n\n## 📦 Installation\n\n```toml\n[dependencies]\nhlskit = \"0.2.0\"\n```\n\n---\n\n## 📌 Requirements\n\n- Rust 1.85+\n- FFmpeg must be installed in your system and available in `$PATH`\n\n---\n\n## 🛣️ Roadmap\n\n- 🔄 GStreamer backend\n- 📦 Crates.io publish\n- 🧪 Comprehensive test coverage\n- 💡 Custom audio profiles \u0026 watermarking\n- 📄 Better documentation\n\n---\n\n## 🪪 License\n\nHlsKit 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.\n\nThe 'HlsKit' name and logo are trademarks of Engels Tercero. Use in forks or derivatives requires written permission.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flike-engels%2Fhlskit-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flike-engels%2Fhlskit-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flike-engels%2Fhlskit-rs/lists"}