Crates.io | icy-metadata |
lib.rs | icy-metadata |
version | |
source | src |
created_at | 2024-06-04 01:55:33.68683+00 |
updated_at | 2025-05-16 04:40:04.133515+00 |
description | A library for parsing Icecast metadata |
homepage | |
repository | https://github.com/aschey/icy-metadata |
max_upload_size | |
id | 1260625 |
Cargo.toml error: | TOML parse error at line 24, column 1 | 24 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
icy-metadata is a library for reading metadata returned from Icecast-compatible web servers.
cargo add icy-metadata
reqwest
- adds convenience methods to set icy metadata headers on
reqwest
's client builder and request builder.serde
- enables serialization/deserialization for metadata structs.Parse common Icecast headers from an HTTP response. icy-metadata
will look for
several common aliases to find the header values.
use icy_metadata::IcyHeaders;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let stream = reqwest::get("https://some-cool-url.com/some-file.mp3").await?;
let icy_headers = IcyHeaders::parse_from_headers(stream.headers());
println!("{icy_headers:?}");
Ok(())
}
Some streams have information about the current track contained within the
stream itself. Wrapping the stream in an IcyMetadataReader
provides an
interface to read those values.
use std::error::Error;
use std::num::NonZeroUsize;
use icy_metadata::{IcyHeaders, IcyMetadataReader, RequestIcyMetadata};
use stream_download::http::HttpStream;
use stream_download::http::reqwest::{self, Client};
use stream_download::storage::bounded::BoundedStorageProvider;
use stream_download::storage::memory::MemoryStorageProvider;
use stream_download::{Settings, StreamDownload};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// We need to add a header to tell the Icecast server that we can parse the metadata
// embedded within the stream itself.
let client = Client::builder().request_icy_metadata().build()?;
let stream =
HttpStream::new(client, "https://some-cool-url.com/some-file.mp3".parse()?).await?;
let icy_headers = IcyHeaders::parse_from_headers(stream.headers());
// buffer 5 seconds of audio
// bitrate (in kilobits) / bits per byte * bytes per kilobyte * 5 seconds
let prefetch_bytes = icy_headers.bitrate().unwrap() / 8 * 1024 * 5;
let reader = StreamDownload::from_stream(
stream,
// use bounded storage to keep the underlying size from growing indefinitely
BoundedStorageProvider::new(
MemoryStorageProvider,
// be liberal with the buffer size, you need to make sure it holds
// enough space to prevent any out-of-bounds reads
NonZeroUsize::new(512 * 1024).unwrap(),
),
Settings::default().prefetch_bytes(prefetch_bytes as u64),
)
.await?;
let metadata_reader = IcyMetadataReader::new(
reader,
// Since we requested icy metadata, the metadata interval header should be
// present in the response. This will allow us to parse the metadata
// within the stream.
icy_headers.metadata_interval(),
// Print the stream metadata whenever we receive new values
|metadata| println!("{metadata:?}\n"),
);
Ok(())
}
Seeking is supported with a few limitations. See the docs for
IcyMetadataReader
for details.
The MSRV is currently 1.85.0
. Since Cargo's V3 resolver supports MSRV-aware
dependencies, we do not treat an MSRV bump as a breaking change.