Fix stream_block buffer cycling issue with FFPlay

PROBLEM:
When streaming Radio Paradise blocks via HTTP using FFPlay, the buffer
would cycle between 0KB and ~130KB approximately once per second, causing
audio dropouts and interruptions. VLC worked fine, but FFPlay was sensitive
to the burst transmission pattern.

ROOT CAUSE:
In StreamingFlacSink::broadcast_flac_stream(), the broadcaster was reading
8KB (8192 bytes) at a time from the FLAC encoder and sending the entire
chunk at once to all HTTP clients. This created a "burst" pattern:
- Read 8KB from encoder
- Send entire 8KB chunk to all clients
- Sleep if ahead of real-time pacing
- Repeat

FFPlay's buffer would fill rapidly with each 8KB burst, then drain completely
before the next burst arrived, causing the observed cycling behavior.

SOLUTION:
Reduced the HTTP broadcast buffer size from 8KB to 512 bytes in
StreamingFlacSink::broadcast_flac_stream(). This creates a much smoother,
more continuous data flow that FFPlay can handle without buffer cycling.

The 512-byte buffer size is:
- Small enough to prevent burst transmission
- Large enough to avoid excessive overhead
- Sufficient for smooth streaming with real-time pacing

CHANGES:
- Restore stream_block.rs example from git history
- Restore StreamingFlacSink and StreamingOggFlacSink from git history
- Add "streaming" feature to pmoaudio-ext
- Reduce broadcast buffer from 8192 to 512 bytes
- Update pmoparadise to use pmoaudio-ext streaming feature

TESTING:
Test with FFPlay to verify smooth buffering:
```bash
cargo run --example stream_block --features full -- 0
# In another terminal:
ffplay http://localhost:8080/test/stream
```

Watch the "aq=" value in FFPlay output. It should now remain stable
instead of cycling between 0KB and 130KB.
This commit is contained in:
Claude
2025-11-13 06:59:27 +00:00
parent 4803c6ab73
commit 69cb3eb80a
7 changed files with 2511 additions and 3 deletions

View File

@@ -16,6 +16,11 @@ pmometadata = { path = "../pmometadata", optional = true }
# Optional dependencies for playlist integration
pmoplaylist = { path = "../pmoplaylist", optional = true }
pmocache = { path = "../pmocache", optional = true }
# Optional dependencies for streaming feature
bytes = { version = "1.5", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
# Async runtime
tokio = { version = "1.0", features = ["full"] }
tokio-util = { version = "0.7" }
@@ -28,4 +33,5 @@ tracing = "0.1"
default = []
cache-sink = ["dep:pmoaudiocache", "dep:pmoflac", "dep:pmometadata"]
playlist = ["cache-sink", "dep:pmoplaylist", "dep:pmocache"]
all = ["cache-sink", "playlist"]
streaming = ["dep:pmoflac", "dep:pmometadata", "dep:bytes", "dep:serde"]
all = ["cache-sink", "playlist", "streaming"]

View File

@@ -9,3 +9,15 @@ mod flac_cache_sink;
#[cfg(feature = "cache-sink")]
pub use flac_cache_sink::{FlacCacheSink, FlacCacheSinkStats, TrackStats};
#[cfg(feature = "streaming")]
mod streaming_flac_sink;
#[cfg(feature = "streaming")]
mod streaming_ogg_flac_sink;
#[cfg(feature = "streaming")]
pub use streaming_flac_sink::{StreamingFlacSink, StreamHandle, MetadataSnapshot};
#[cfg(feature = "streaming")]
pub use streaming_ogg_flac_sink::{StreamingOggFlacSink, OggFlacStreamHandle};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff