feat: 新增 client-kws
This commit is contained in:
Generated
+3
-3
@@ -308,6 +308,7 @@ name = "open-xiaoai"
|
|||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -385,13 +386,12 @@ checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.9.0"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"zerocopy",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ version = "1.0.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
strip = true
|
strip = true
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
[workspace.metadata.cross.target.armv7-unknown-linux-gnueabihf]
|
[workspace.metadata.cross.target.armv7-unknown-linux-gnueabihf]
|
||||||
@@ -21,3 +21,4 @@ tokio-tungstenite = "0.26.2"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
uuid = { version = "1.15.1", features = ["v4"] }
|
uuid = { version = "1.15.1", features = ["v4"] }
|
||||||
|
rand = "0.9.1"
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use open_xiaoai::{
|
||||||
|
services::monitor::kws::{KwsMonitor, KwsMonitorEvent, KWS_FILE_PATH},
|
||||||
|
utils::{rand::pick_one, shell::run_shell},
|
||||||
|
};
|
||||||
|
|
||||||
|
static KWS_REPLY_FILE_PATH: &str = "/data/open-xiaoai/kws/reply.txt";
|
||||||
|
|
||||||
|
async fn on_started() {
|
||||||
|
let welcome = std::env::args()
|
||||||
|
.nth(1)
|
||||||
|
.unwrap_or("自定义唤醒词已开启".to_string());
|
||||||
|
let _ = run_shell(&format!("/usr/sbin/tts_play.sh '{}'", welcome)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn on_keyword(_keyword: String) {
|
||||||
|
println!("🔥 唤醒词: {}", _keyword);
|
||||||
|
|
||||||
|
let mut wakeup_sounds = vec![
|
||||||
|
"file:///usr/share/sound-vendor/AiNiRobot/wakeup_ei_01.wav".to_string(),
|
||||||
|
"file:///usr/share/sound-vendor/AiNiRobot/wakeup_zai_01.wav".to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if Path::new(KWS_REPLY_FILE_PATH).exists() {
|
||||||
|
// 播放自定义唤醒提示音
|
||||||
|
let content = std::fs::read_to_string(KWS_REPLY_FILE_PATH).unwrap();
|
||||||
|
let replies = content
|
||||||
|
.split("\n")
|
||||||
|
.filter(|line| !line.trim().is_empty())
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
if replies.len() > 0 {
|
||||||
|
wakeup_sounds.clear();
|
||||||
|
wakeup_sounds.extend(replies.iter().map(|s| s.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let reply = pick_one(&wakeup_sounds);
|
||||||
|
let script = if reply.contains("://") {
|
||||||
|
format!("miplayer -f '{}'", reply)
|
||||||
|
} else {
|
||||||
|
format!("/usr/sbin/tts_play.sh '{}'", reply)
|
||||||
|
};
|
||||||
|
let _ = run_shell(&script).await;
|
||||||
|
|
||||||
|
// 唤醒
|
||||||
|
let _ = run_shell(r#"ubus call pnshelper event_notify '{"src":1,"event":0}'"#).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
if Path::new(KWS_FILE_PATH).exists() {
|
||||||
|
on_started().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
KwsMonitor::start(|event| async move {
|
||||||
|
match event {
|
||||||
|
KwsMonitorEvent::Started => on_started().await,
|
||||||
|
KwsMonitorEvent::Keyword(keyword) => on_keyword(keyword).await,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ pub enum KwsMonitorEvent {
|
|||||||
|
|
||||||
pub struct KwsMonitor;
|
pub struct KwsMonitor;
|
||||||
|
|
||||||
static KWS_FILE_PATH: &str = "/tmp/open-xiaoai/kws.log";
|
pub static KWS_FILE_PATH: &str = "/tmp/open-xiaoai/kws.log";
|
||||||
|
|
||||||
static LAST_TIMESTAMP: AtomicU64 = AtomicU64::new(0);
|
static LAST_TIMESTAMP: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod shell;
|
pub mod shell;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
|
pub mod rand;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
use rand::seq::IndexedRandom;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static RNG: RefCell<rand::rngs::ThreadRng> = RefCell::new(rand::rng());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pick_one<T>(items: &[T]) -> &T {
|
||||||
|
RNG.with(|rng| items.choose(&mut *rng.borrow_mut()).unwrap())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user