Streaming FLAC manipulation
- Rust 100%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| crates/flactag | ||
| .editorconfig | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
| rust-toolchain.toml | ||
| rustfmt.toml | ||
| typos.toml | ||
FLACtag: streaming FLAC manipulation
Usage (read)
Read a file and print its tags and pictures:
use std::fs::File;
use flactag::{FlacBlock, FlacReader};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = File::open("song.flac")?;
for block in FlacReader::new(file) {
match block? {
FlacBlock::Streaminfo(s) => {
println!("{} Hz, {} channels, {} bps", s.sample_rate, s.channels, s.bits_per_sample);
}
FlacBlock::VorbisComment(c) => {
for (tag, value) in &c.comment.comments {
println!("{tag:?} = {value}");
}
// Pictures stored as METADATA_BLOCK_PICTURE comments show up here
for picture in &c.comment.pictures {
println!("inline picture: {} ({} bytes)", picture.mime, picture.img_data.len());
}
}
FlacBlock::Picture(p) => {
println!("{:?} picture: {} ({}x{})", p.picture_type, p.mime, p.width, p.height);
}
// Padding, Application, SeekTable, CueSheet, AudioFrame
_ => {}
}
}
Ok(())
}
Usage (write)
FLAC writing features of this crate are not finished.
Blocks are re-encoded with FlacBlock::encode(is_last, with_header, target). is_last sets the
last-metadata-block flag in the header, and with_header controls whether the 4-byte metablock
header is written (audio frames ignore both). A full round-trip looks like this:
use std::{fs::File, io::Write};
use flactag::{FlacBlock, FlacReader};
fn copy(from: &str, to: &str) -> Result<(), Box<dyn std::error::Error>> {
let blocks: Vec<FlacBlock> = FlacReader::new(File::open(from)?).collect::<Result<_, _>>()?;
let mut out = File::create(to)?;
out.write_all(b"fLaC")?;
for (i, block) in blocks.iter().enumerate() {
// The last metablock is the one right before the first audio frame
let is_last = !matches!(block, FlacBlock::AudioFrame(_))
&& matches!(blocks.get(i + 1), Some(FlacBlock::AudioFrame(_)));
block.encode(is_last, true, &mut out)?;
}
Ok(())
}