feat(video): 事务化切换与前端统一编排,增强视频输入格式支持

- 后端:切换事务+transition_id,/stream/mode 返回 switching/transition_id 与实际 codec

- 事件:新增 mode_switching/mode_ready,config/webrtc_ready/mode_changed 关联事务

- 编码/格式:扩展 NV21/NV16/NV24/RGB/BGR 输入与转换链路,RKMPP direct input 优化

- 前端:useVideoSession 统一切换,失败回退真实切回 MJPEG,菜单格式同步修复

- 清理:useVideoStream 降级为 MJPEG-only
This commit is contained in:
mofeng-git
2026-01-11 10:41:57 +08:00
parent 9feb74b72c
commit 206594e292
110 changed files with 3955 additions and 2251 deletions

View File

@@ -193,7 +193,9 @@ impl AudioController {
pub async fn select_device(&self, device: &str) -> Result<()> {
// Validate device exists
let devices = self.list_devices().await?;
let found = devices.iter().any(|d| d.name == device || d.description.contains(device));
let found = devices
.iter()
.any(|d| d.name == device || d.description.contains(device));
if !found && device != "default" {
return Err(AppError::AudioError(format!(
@@ -244,7 +246,11 @@ impl AudioController {
})
.await;
info!("Audio quality set to: {:?} ({}bps)", quality, quality.bitrate());
info!(
"Audio quality set to: {:?} ({}bps)",
quality,
quality.bitrate()
);
Ok(())
}
@@ -346,14 +352,17 @@ impl AudioController {
let streaming = self.is_streaming().await;
let error = self.last_error.read().await.clone();
let (subscriber_count, frames_encoded, bytes_output) = if let Some(ref streamer) =
*self.streamer.read().await
{
let stats = streamer.stats().await;
(stats.subscriber_count, stats.frames_encoded, stats.bytes_output)
} else {
(0, 0, 0)
};
let (subscriber_count, frames_encoded, bytes_output) =
if let Some(ref streamer) = *self.streamer.read().await {
let stats = streamer.stats().await;
(
stats.subscriber_count,
stats.frames_encoded,
stats.bytes_output,
)
} else {
(0, 0, 0)
};
AudioStatus {
enabled: config.enabled,
@@ -383,7 +392,11 @@ impl AudioController {
/// Subscribe to Opus frames (async version)
pub async fn subscribe_opus_async(&self) -> Option<broadcast::Receiver<OpusFrame>> {
self.streamer.read().await.as_ref().map(|s| s.subscribe_opus())
self.streamer
.read()
.await
.as_ref()
.map(|s| s.subscribe_opus())
}
/// Enable or disable audio