Add audio.rs for audio playback

This commit is contained in:
2026-03-19 00:31:26 +08:00
parent 86814d43de
commit a438981ad5

84
src/player/audio.rs Normal file
View File

@@ -0,0 +1,84 @@
//! 音頻播放模組
use anyhow::Result;
use std::process::{Command, Stdio};
use std::io::Write;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub struct AudioPlayer {
process: Option<std::process::Child>,
volume: f32,
muted: bool,
}
impl AudioPlayer {
pub fn new() -> Self {
Self {
process: None,
volume: 1.0,
muted: false,
}
}
pub fn play(&mut self, path: &str, start_ms: u64) -> Result<()> {
self.stop()?;
let start_sec = start_ms as f64 / 1000.0;
let volume_filter = if self.muted {
"volume=0".to_string()
} else {
format!("volume={}", self.volume)
};
let mut cmd = Command::new("ffplay");
cmd.args([
"-nodisp",
"-autoexit",
"-ss", &format!("{}", start_sec),
"-af", &volume_filter,
"-i", path,
])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()?;
self.process = Some(cmd);
Ok(())
}
pub fn stop(&mut self) -> Result<()> {
if let Some(mut child) = self.process.take() {
let _ = child.kill();
let _ = child.wait();
}
Ok(())
}
pub fn set_volume(&mut self, volume: f32) {
self.volume = volume.clamp(0.0, 1.0);
if !self.muted {
self.restart_with_volume()?;
}
}
pub fn toggle_mute(&mut self) -> bool {
self.muted = !self.muted;
self.muted
}
pub fn is_muted(&self) -> bool {
self.muted
}
fn restart_with_volume(&mut self) -> Result<()> {
Ok(())
}
}
impl Drop for AudioPlayer {
fn drop(&mut self) {
let _ = self.stop();
}
}