fix: increase radio playback buffer

This commit is contained in:
Bjarne Øverli
2026-08-13 19:32:50 +02:00
parent ab1d0c6caf
commit 05b6986ac0
8 changed files with 26 additions and 16 deletions
+1
View File
@@ -0,0 +1 @@
I use AI, and if this file is not deleted, I haven't reviewed my own code.
+1 -1
View File
@@ -38,7 +38,7 @@ func buildApp() *cli.Command {
&cli.StringFlag{Name: "visualizer", Usage: "visualizer mode"},
&cli.StringFlag{Name: "eq-preset", Usage: "EQ preset name"},
&cli.IntFlag{Name: "sample-rate", Usage: "output sample rate in Hz (0=auto)", HideDefault: true},
&cli.IntFlag{Name: "buffer-ms", Usage: "speaker buffer in milliseconds (50-500)", HideDefault: true},
&cli.IntFlag{Name: "buffer-ms", Usage: "speaker buffer in milliseconds (50-5000)", HideDefault: true},
&cli.IntFlag{Name: "resample-quality", Usage: "resample quality factor (1-4)", HideDefault: true},
&cli.IntFlag{Name: "bit-depth", Usage: "PCM bit depth: 16 or 32", HideDefault: true},
&cli.StringFlag{Name: "audio-device", Usage: "audio output device (use 'list' to show)"},
+1 -1
View File
@@ -29,7 +29,7 @@ seek_large_step_sec = 30
# Advanced audio settings (most users don't need to change these)
# sample_rate = 0 # 0=auto-detect, or 22050/44100/48000/96000/192000
# buffer_ms = 100 # speaker buffer in ms (50-500)
# buffer_ms = 250 # speaker buffer in ms (50-5000; try 2000 for unstable radio streams)
# resample_quality = 4 # 1-4, where 4 is best
# bit_depth = 16 # 16 or 32 (for FFmpeg-decoded formats)
+3 -3
View File
@@ -251,7 +251,7 @@ type Config struct {
Theme string // theme name, or "" for ANSI default
Visualizer string // visualizer mode name, or "" for default (Bars)
SampleRate int // output sample rate: 22050, 44100, 48000, 96000, 192000
BufferMs int // speaker buffer in milliseconds (50500)
BufferMs int // speaker buffer in milliseconds (50-5000)
ResampleQuality int // beep resample quality factor (14)
BitDepth int // PCM bit depth for FFmpeg output: 16 or 32
Compact bool // compact mode: cap frame width at 80 columns
@@ -287,7 +287,7 @@ func defaultConfig() Config {
Speed: 1.0,
SeekStepLarge: 30,
SampleRate: 0,
BufferMs: 100,
BufferMs: 250,
ResampleQuality: 4,
BitDepth: 16,
PaddingH: 3,
@@ -763,7 +763,7 @@ func (c *Config) clamp() {
}
c.SeekStepLarge = max(min(c.SeekStepLarge, 600), 6)
c.SampleRate = clampSampleRate(c.SampleRate)
c.BufferMs = max(min(c.BufferMs, 500), 50)
c.BufferMs = max(min(c.BufferMs, 5000), 50)
c.ResampleQuality = max(min(c.ResampleQuality, 4), 1)
c.BitDepth = clampBitDepth(c.BitDepth)
c.Spotify.Bitrate = clampSpotifyBitrate(c.Spotify.Bitrate)
+5 -4
View File
@@ -22,8 +22,8 @@ func TestDefaultConfig(t *testing.T) {
if cfg.SampleRate != 0 {
t.Errorf("SampleRate = %d, want 0 (auto)", cfg.SampleRate)
}
if cfg.BufferMs != 100 {
t.Errorf("BufferMs = %d, want 100", cfg.BufferMs)
if cfg.BufferMs != 250 {
t.Errorf("BufferMs = %d, want 250", cfg.BufferMs)
}
if cfg.ResampleQuality != 4 {
t.Errorf("ResampleQuality = %d, want 4", cfg.ResampleQuality)
@@ -223,9 +223,10 @@ func TestClampBufferMs(t *testing.T) {
}{
{100, 100},
{10, 50},
{600, 500},
{600, 600},
{50, 50},
{500, 500},
{5000, 5000},
{5001, 5000},
}
for _, tt := range tests {
cfg := defaultConfig()
+12 -4
View File
@@ -10,8 +10,8 @@ Add any of these to your config file:
# Output sample rate in Hz (22050, 44100, 48000, 96000, 192000)
sample_rate = 44100
# Speaker buffer in milliseconds (50-500)
buffer_ms = 100
# Speaker buffer in milliseconds (50-5000)
buffer_ms = 250
# Resample quality (1-4, where 4 is best)
resample_quality = 4
@@ -27,7 +27,7 @@ All four are optional. Defaults are shown above.
| Setting | Effect |
|--------------------|------------------------------------------------------------------------|
| `sample_rate` | Output rate sent to your sound card. 48000 matches most modern DACs. |
| `buffer_ms` | Lower = less latency, higher = fewer glitches. Try 200 if audio pops. |
| `buffer_ms` | Lower = less latency, higher = fewer glitches. Try 200 if audio pops, or 2000 for unstable radio streams. |
| `resample_quality` | Sinc interpolation quality when a file's native rate differs from output. 4 is best, 1 is fastest. |
| `bit_depth` | PCM precision for FFmpeg-decoded formats (m4a, aac, alac, opus, wma, webm). 32 uses float PCM which preserves up to 24-bit audio without truncation. Native formats (mp3, flac, wav, ogg) always decode at full precision regardless of this setting. |
@@ -37,7 +37,7 @@ All four are optional. Defaults are shown above.
```toml
sample_rate = 96000
buffer_ms = 100
buffer_ms = 250
resample_quality = 4
bit_depth = 32
```
@@ -50,4 +50,12 @@ buffer_ms = 200
resample_quality = 1
```
**Unstable radio connection**:
```toml
buffer_ms = 2000
```
This adds up to two seconds of playback latency, but gives the audio device more time to absorb short network interruptions.
Changes take effect on next launch.
+2 -2
View File
@@ -18,7 +18,7 @@ cliamp --playlist "Blade Runner" # load a local TOML playlist (add --auto-p
```sh
cliamp --sample-rate 48000 track.mp3 # output sample rate (22050, 44100, 48000, 96000, 192000)
cliamp --buffer-ms 200 track.mp3 # speaker buffer in ms (50500)
cliamp --buffer-ms 2000 track.mp3 # speaker buffer in ms (50-5000; useful for unstable radio)
cliamp --resample-quality 1 track.mp3 # resample quality factor (14)
cliamp --bit-depth 32 track.m4a # PCM bit depth: 16 (default) or 32 (lossless)
```
@@ -116,7 +116,7 @@ cliamp track.mp3 --repeat all --mono ~/Music
| `--theme` | string | | theme name |
| `--eq-preset` | string | | preset name |
| `--sample-rate` | int | 44100 | 22050, 44100, 48000, 96000, 192000 |
| `--buffer-ms` | int | 100 | 50500 |
| `--buffer-ms` | int | 250 | 50-5000 |
| `--resample-quality` | int | 4 | 14 |
| `--bit-depth` | int | 16 | 16, 32 |
| `--playlist` | string | | local TOML playlist name |
+1 -1
View File
@@ -757,7 +757,7 @@ user_id = "your-account-user-id"</code></pre>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Gapless Playback</div><p>Seamless transitions with preloaded next-track buffering.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">MPRIS / Media Keys</div><p>Desktop integration. Hardware media keys, <code>playerctl</code>, and embedded local cover art.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Quickshell Widget (Omarchy)</div><p>Drop-in <a href="https://quickshell.org">Quickshell</a> now-playing card with a Winamp 2-style spectrum, tracking your active Omarchy theme. <a href="https://github.com/bjarneo/cliamp/blob/main/docs/quickshell.md">Setup</a>.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Audio Quality</div><p>Configurable sample rate (22kHz192kHz), buffer size, resample.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Audio Quality</div><p>Configurable sample rate (22kHz-192kHz), up to 5 seconds of buffering, and resampling.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Live Radio Metadata</div><p>ICY/Shoutcast metadata for the current song on internet radio, plus API-based now-playing for FIP and NTS.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">Embedded Tag Reading</div><p>ID3v2, Vorbis comments, MP4 atoms - artist, album, genre, year, lyrics, cover art.</p></div>
<div class="feature"><div class="feature-icon"></div><div class="feature-name">CLI Flags</div><p>Override volume, shuffle, repeat, theme, EQ, sample rate per-session.</p></div>