| Crates.io | ts2mp4 |
| lib.rs | ts2mp4 |
| version | 0.2.0 |
| created_at | 2026-01-14 05:17:16.835678+00 |
| updated_at | 2026-01-22 07:47:24.86877+00 |
| description | A library and CLI tool for converting MPEG-TS files to MP4 format |
| homepage | https://github.com/aciddust/ts2mp4 |
| repository | https://github.com/aciddust/ts2mp4 |
| max_upload_size | |
| id | 2042221 |
| size | 574,726 |
A Rust library that converts MPEG-2 TS (Transport Stream) files to MP4 format. Can be compiled to WebAssembly for use in web browsers.
This project started as a personal implementation to understand TS (Transport Stream) and MP4 formats, and for this reason, the content may be somewhat rough around the edges.
If you wanna specific version, add to your Cargo.toml:
[dependencies]
ts2mp4 = "0.1.0"
then...
use ts2mp4::{convert_ts_to_mp4, extract_thumbnail_from_ts, extract_thumbnail_from_mp4};
use std::fs;
fn main() -> std::io::Result<()> {
// Convert TS to MP4
let ts_data = fs::read("input.ts")?;
let mp4_data = convert_ts_to_mp4(&ts_data)?;
fs::write("output.mp4", mp4_data)?;
// Extract thumbnail from TS
let thumbnail_data = extract_thumbnail_from_ts(&ts_data)?;
fs::write("thumbnail_ts.h264", thumbnail_data)?;
// Extract thumbnail from MP4
let mp4_data = fs::read("input.mp4")?;
let thumbnail_data = extract_thumbnail_from_mp4(&mp4_data)?;
fs::write("thumbnail_mp4.h264", thumbnail_data)?;
Ok(())
}
cargo install ts2mp4
# Convert TS to MP4
cargo run --release -- convert input.ts output.mp4
# Extract thumbnail from TS file
cargo run --release -- thumbnail-ts input.ts thumbnail.h264
# Extract thumbnail from MP4 file
cargo run --release -- thumbnail-mp4 input.mp4 thumbnail.h264
The thumbnail is extracted as a raw H.264 keyframe (I-frame) which can be:
ffmpeg -i thumbnail.h264 -frames:v 1 thumbnail.jpg# dev
cargo build
# release
cargo build --release
# then
./target/release/ts2mp4 ${INPUT_TS} ${OUTPUT_MP4}
Build from source:
# Install wasm-pack
cargo install wasm-pack
# Build
wasm-pack build --target web
This will generate the following files in the pkg/ directory:
ts2mp4.js - JavaScript bindingsts2mp4_bg.wasm - WebAssembly binaryts2mp4.d.ts - TypeScript type definitionsExamples:
import init, {
convert_ts_to_mp4_wasm,
extract_thumbnail_from_ts_wasm,
extract_thumbnail_from_mp4_wasm
} from './pkg/ts2mp4.js';
// Initialize WASM
await init();
// Convert TS to MP4
const tsData = new Uint8Array(await file.arrayBuffer());
const mp4Data = convert_ts_to_mp4_wasm(tsData);
// Extract thumbnail from TS
const thumbnailFromTs = extract_thumbnail_from_ts_wasm(tsData);
// Extract thumbnail from MP4
const mp4Data = new Uint8Array(await mp4File.arrayBuffer());
const thumbnailFromMp4 = extract_thumbnail_from_mp4_wasm(mp4Data);
This library is intentionally designed not to use SharedArrayBuffer:
Good performance can be achieved without SharedArrayBuffer:
// Example using Web Worker
// worker.js
import init, { convert_ts_to_mp4_wasm } from './pkg/ts2mp4.js';
self.onmessage = async (e) => {
await init();
try {
const mp4Data = convert_ts_to_mp4_wasm(e.data);
self.postMessage({ success: true, data: mp4Data });
} catch (error) {
self.postMessage({ success: false, error: error.message });
}
};
// main.js
const worker = new Worker('worker.js', { type: 'module' });
worker.onmessage = (e) => {
if (e.data.success) {
// Process MP4 data
const blob = new Blob([e.data.data], { type: 'video/mp4' });
// ...
} else {
console.error('Conversion failed:', e.data.error);
}
};
// Start conversion
worker.postMessage(tsData);
For detailed development and debugging instructions, see DEV_GUIDE.md.
# Build
cargo build --release
# Test
./target/release/ts2mp4 input.ts output.mp4
# Verify
ffprobe output.mp4
ffplay output.mp4
The test-scripts/ directory contains Python scripts for analyzing MP4 file structure:
test-scripts/analyze_mp4.py - Analyze box structuretest-scripts/check_all_durations.py - Verify durationstest-scripts/check_stts.py - Check Time-to-Sampletest-scripts/verify_audio_data.py - Verify audio data positionsFor detailed usage, refer to DEV_GUIDE.md.
For common issues and solutions, refer to the "Troubleshooting" section in DEV_GUIDE.md.
| docs | description | lang |
|---|---|---|
| TS_STRUCTURE.md | TS packet generation and processing | ko, en |
| MP4_STRUCTURE.md | MP4 generation and structure | ko, en |
| 90kHZ_MAGIC.md | Why is 90kHz used for frame synchronization? | ko, en |
MIT
Issues and PRs are always welcome!