mirror of https://github.com/jetkvm/kvm.git
Make audio sample rate user-configurable
- Add sample rate dropdown in UI with Opus-supported rates (8k/12k/16k/24k/48kHz) - Add sampleRate parameter to setAudioConfig RPC handler - Validate sample rate is one of the 5 Opus-compatible values - Configuration takes effect on next audio restart (Apply button)
This commit is contained in:
parent
584b9fe3bf
commit
1dfb4ab77f
|
|
@ -1000,7 +1000,7 @@ func rpcGetAudioConfig() (AudioConfigResponse, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func rpcSetAudioConfig(bitrate int, complexity int, dtxEnabled bool, fecEnabled bool, bufferPeriods int, packetLossPerc int) error {
|
||||
func rpcSetAudioConfig(bitrate int, complexity int, dtxEnabled bool, fecEnabled bool, bufferPeriods int, sampleRate int, packetLossPerc int) error {
|
||||
ensureConfigLoaded()
|
||||
|
||||
if bitrate < 64 || bitrate > 256 {
|
||||
|
|
@ -1012,6 +1012,10 @@ func rpcSetAudioConfig(bitrate int, complexity int, dtxEnabled bool, fecEnabled
|
|||
if bufferPeriods < 2 || bufferPeriods > 24 {
|
||||
return fmt.Errorf("buffer periods must be between 2 and 24")
|
||||
}
|
||||
validSampleRates := map[int]bool{8000: true, 12000: true, 16000: true, 24000: true, 48000: true}
|
||||
if !validSampleRates[sampleRate] {
|
||||
return fmt.Errorf("sample rate must be one of: 8000, 12000, 16000, 24000, 48000 Hz")
|
||||
}
|
||||
if packetLossPerc < 0 || packetLossPerc > 100 {
|
||||
return fmt.Errorf("packet loss percentage must be between 0 and 100")
|
||||
}
|
||||
|
|
@ -1021,6 +1025,7 @@ func rpcSetAudioConfig(bitrate int, complexity int, dtxEnabled bool, fecEnabled
|
|||
config.AudioDTXEnabled = dtxEnabled
|
||||
config.AudioFECEnabled = fecEnabled
|
||||
config.AudioBufferPeriods = bufferPeriods
|
||||
config.AudioSampleRate = sampleRate
|
||||
config.AudioPacketLossPerc = packetLossPerc
|
||||
|
||||
return SaveConfig()
|
||||
|
|
@ -1375,7 +1380,7 @@ var rpcHandlers = map[string]RPCHandler{
|
|||
"setAudioOutputSource": {Func: rpcSetAudioOutputSource, Params: []string{"source"}},
|
||||
"refreshHdmiConnection": {Func: rpcRefreshHdmiConnection},
|
||||
"getAudioConfig": {Func: rpcGetAudioConfig},
|
||||
"setAudioConfig": {Func: rpcSetAudioConfig, Params: []string{"bitrate", "complexity", "dtxEnabled", "fecEnabled", "bufferPeriods", "packetLossPerc"}},
|
||||
"setAudioConfig": {Func: rpcSetAudioConfig, Params: []string{"bitrate", "complexity", "dtxEnabled", "fecEnabled", "bufferPeriods", "sampleRate", "packetLossPerc"}},
|
||||
"restartAudioOutput": {Func: rpcRestartAudioOutput},
|
||||
"getAudioInputAutoEnable": {Func: rpcGetAudioInputAutoEnable},
|
||||
"setAudioInputAutoEnable": {Func: rpcSetAudioInputAutoEnable, Params: []string{"enabled"}},
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ export default function SettingsAudioRoute() {
|
|||
dtxEnabled: audioDTXEnabled,
|
||||
fecEnabled: audioFECEnabled,
|
||||
bufferPeriods: audioBufferPeriods,
|
||||
sampleRate: audioSampleRate,
|
||||
packetLossPerc: audioPacketLossPerc,
|
||||
});
|
||||
|
||||
|
|
@ -153,12 +154,12 @@ export default function SettingsAudioRoute() {
|
|||
send("setAudioConfig", config, (resp: JsonRpcResponse) => {
|
||||
if (handleRpcError(resp)) return;
|
||||
|
||||
// Update all state values from the config
|
||||
setAudioBitrate(config.bitrate);
|
||||
setAudioComplexity(config.complexity);
|
||||
setAudioDTXEnabled(config.dtxEnabled);
|
||||
setAudioFECEnabled(config.fecEnabled);
|
||||
setAudioBufferPeriods(config.bufferPeriods);
|
||||
setAudioSampleRate(config.sampleRate);
|
||||
setAudioPacketLossPerc(config.packetLossPerc);
|
||||
notifications.success(m.audio_settings_config_updated());
|
||||
});
|
||||
|
|
@ -292,20 +293,18 @@ export default function SettingsAudioRoute() {
|
|||
title={m.audio_settings_sample_rate_title()}
|
||||
description={m.audio_settings_sample_rate_description()}
|
||||
>
|
||||
<div className="text-sm text-gray-700 dark:text-gray-300 font-medium">
|
||||
{(() => {
|
||||
const rateMap: Record<number, string> = {
|
||||
32000: "32 kHz",
|
||||
44100: "44.1 kHz",
|
||||
48000: "48 kHz",
|
||||
96000: "96 kHz"
|
||||
};
|
||||
return rateMap[audioSampleRate] || `${audioSampleRate} Hz`;
|
||||
})()}
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400 ml-2">
|
||||
(auto-detected from source)
|
||||
</span>
|
||||
</div>
|
||||
<SelectMenuBasic
|
||||
size="SM"
|
||||
value={String(audioSampleRate)}
|
||||
options={[
|
||||
{ value: "8000", label: "8 kHz" },
|
||||
{ value: "12000", label: "12 kHz" },
|
||||
{ value: "16000", label: "16 kHz" },
|
||||
{ value: "24000", label: "24 kHz" },
|
||||
{ value: "48000", label: "48 kHz (default)" },
|
||||
]}
|
||||
onChange={(e) => handleAudioConfigChange({ sampleRate: parseInt(e.target.value) })}
|
||||
/>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem
|
||||
|
|
|
|||
Loading…
Reference in New Issue