Spaces:
Sleeping
Sleeping
use debian:bookworm-slim as runtime image
Browse files- Dockerfile +2 -3
- src/asr/aws.rs +4 -5
- src/asr/mod.rs +11 -1
- src/lesson.rs +3 -3
- src/main.rs +0 -5
- static/index.html +1 -1
- tests/stream_single.rs +5 -4
Dockerfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
FROM rust:
|
2 |
RUN apt-get update && apt-get install -y curl
|
3 |
RUN cargo install cargo-chef
|
4 |
WORKDIR /app
|
@@ -14,8 +14,7 @@ COPY . .
|
|
14 |
RUN cargo chef cook --release --recipe-path recipe.json
|
15 |
RUN cargo build --release
|
16 |
|
17 |
-
FROM
|
18 |
-
|
19 |
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
|
20 |
WORKDIR /app
|
21 |
COPY --from=builder /app/target/release/polyhedron .
|
|
|
1 |
+
FROM rust:slim as chef
|
2 |
RUN apt-get update && apt-get install -y curl
|
3 |
RUN cargo install cargo-chef
|
4 |
WORKDIR /app
|
|
|
14 |
RUN cargo chef cook --release --recipe-path recipe.json
|
15 |
RUN cargo build --release
|
16 |
|
17 |
+
FROM debian:bookworm-slim as runtime
|
|
|
18 |
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
|
19 |
WORKDIR /app
|
20 |
COPY --from=builder /app/target/release/polyhedron .
|
src/asr/aws.rs
CHANGED
@@ -12,8 +12,8 @@ use tokio::select;
|
|
12 |
use tokio::sync::broadcast::Receiver;
|
13 |
use tokio_stream::Stream;
|
14 |
use futures_util::TryStreamExt;
|
15 |
-
use tracing::trace;
|
16 |
-
use crate::asr::{ASR, Event,
|
17 |
|
18 |
pub struct AwsAsr {
|
19 |
speaker_voice_channel: tokio::sync::mpsc::Sender<Vec<i16>>,
|
@@ -42,7 +42,7 @@ impl AwsAsr {
|
|
42 |
let fut = async {
|
43 |
let input_stream = stream! {
|
44 |
while let Some(raw) = speaker_voice_rx.recv().await {
|
45 |
-
let reshape =
|
46 |
yield Ok(AudioStream::AudioEvent(AudioEvent::builder().audio_chunk(Blob::new(reshape)).build()));
|
47 |
}
|
48 |
};
|
@@ -59,7 +59,6 @@ impl AwsAsr {
|
|
59 |
let output_stream = to_stream(output);
|
60 |
output_stream
|
61 |
.try_for_each(|text| async {
|
62 |
-
trace!("here");
|
63 |
let _ = shared_speaker_transcript.send(text);
|
64 |
Ok(())
|
65 |
})
|
@@ -69,7 +68,7 @@ impl AwsAsr {
|
|
69 |
select! {
|
70 |
res = fut => {
|
71 |
if let Err(e) = res {
|
72 |
-
|
73 |
}
|
74 |
}
|
75 |
_ = drop_rx => {}
|
|
|
12 |
use tokio::sync::broadcast::Receiver;
|
13 |
use tokio_stream::Stream;
|
14 |
use futures_util::TryStreamExt;
|
15 |
+
use tracing::{trace, warn};
|
16 |
+
use crate::asr::{ASR, Event, slice_i16_to_u8_le};
|
17 |
|
18 |
pub struct AwsAsr {
|
19 |
speaker_voice_channel: tokio::sync::mpsc::Sender<Vec<i16>>,
|
|
|
42 |
let fut = async {
|
43 |
let input_stream = stream! {
|
44 |
while let Some(raw) = speaker_voice_rx.recv().await {
|
45 |
+
let reshape = slice_i16_to_u8_le(&raw);
|
46 |
yield Ok(AudioStream::AudioEvent(AudioEvent::builder().audio_chunk(Blob::new(reshape)).build()));
|
47 |
}
|
48 |
};
|
|
|
59 |
let output_stream = to_stream(output);
|
60 |
output_stream
|
61 |
.try_for_each(|text| async {
|
|
|
62 |
let _ = shared_speaker_transcript.send(text);
|
63 |
Ok(())
|
64 |
})
|
|
|
68 |
select! {
|
69 |
res = fut => {
|
70 |
if let Err(e) = res {
|
71 |
+
warn!("Error: {:?}", e);
|
72 |
}
|
73 |
}
|
74 |
_ = drop_rx => {}
|
src/asr/mod.rs
CHANGED
@@ -18,7 +18,7 @@ pub(crate) trait ASR {
|
|
18 |
}
|
19 |
|
20 |
|
21 |
-
pub fn
|
22 |
slice
|
23 |
.iter()
|
24 |
.flat_map(|&sample| {
|
@@ -27,3 +27,13 @@ pub fn slice_i16_to_u8(slice: &[i16]) -> Vec<u8> {
|
|
27 |
.collect()
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
19 |
|
20 |
|
21 |
+
pub fn slice_i16_to_u8_le(slice: &[i16]) -> Vec<u8> {
|
22 |
slice
|
23 |
.iter()
|
24 |
.flat_map(|&sample| {
|
|
|
27 |
.collect()
|
28 |
}
|
29 |
|
30 |
+
pub fn slice_i16_to_u8_be(slice: &[i16]) -> Vec<u8> {
|
31 |
+
slice
|
32 |
+
.iter()
|
33 |
+
.flat_map(|&sample| {
|
34 |
+
[(sample >> 8) as u8, sample as u8]
|
35 |
+
})
|
36 |
+
.collect()
|
37 |
+
}
|
38 |
+
|
39 |
+
|
src/lesson.rs
CHANGED
@@ -8,7 +8,7 @@ use std::io::BufRead;
|
|
8 |
use std::ops::Deref;
|
9 |
use std::sync::{Arc, Weak};
|
10 |
use tokio::sync::RwLock;
|
11 |
-
use tracing::{error};
|
12 |
|
13 |
use tokio::select;
|
14 |
use crate::asr::{Event, aws::AwsAsr, ASR};
|
@@ -296,7 +296,7 @@ impl LangLesson {
|
|
296 |
select! {
|
297 |
res = fut => {
|
298 |
if let Err(e) = res {
|
299 |
-
|
300 |
}
|
301 |
}
|
302 |
_ = drop_rx => {}
|
@@ -411,7 +411,7 @@ impl InnerVoiceLesson {
|
|
411 |
res = fut => match res {
|
412 |
Ok(_) => {}
|
413 |
Err(e) => {
|
414 |
-
|
415 |
}
|
416 |
},
|
417 |
_ = rx => {}
|
|
|
8 |
use std::ops::Deref;
|
9 |
use std::sync::{Arc, Weak};
|
10 |
use tokio::sync::RwLock;
|
11 |
+
use tracing::{error, warn};
|
12 |
|
13 |
use tokio::select;
|
14 |
use crate::asr::{Event, aws::AwsAsr, ASR};
|
|
|
296 |
select! {
|
297 |
res = fut => {
|
298 |
if let Err(e) = res {
|
299 |
+
warn!("Error: {:?}", e);
|
300 |
}
|
301 |
}
|
302 |
_ = drop_rx => {}
|
|
|
411 |
res = fut => match res {
|
412 |
Ok(_) => {}
|
413 |
Err(e) => {
|
414 |
+
warn!("Error: {:?}", e);
|
415 |
}
|
416 |
},
|
417 |
_ = rx => {}
|
src/main.rs
CHANGED
@@ -4,9 +4,7 @@
|
|
4 |
*/
|
5 |
|
6 |
use aws_config::BehaviorVersion;
|
7 |
-
use aws_sdk_transcribestreaming::meta::PKG_VERSION;
|
8 |
use tokio::select;
|
9 |
-
use tracing::{debug};
|
10 |
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
11 |
|
12 |
use polyhedron::app;
|
@@ -19,11 +17,8 @@ async fn main() -> Result<(), std::io::Error> {
|
|
19 |
.with(EnvFilter::from_default_env())
|
20 |
.init();
|
21 |
|
22 |
-
debug!("Transcribe client version: {}", PKG_VERSION);
|
23 |
-
|
24 |
let shared_config = aws_config::load_defaults(BehaviorVersion::latest()).await;
|
25 |
|
26 |
-
|
27 |
select! {
|
28 |
res = app(&shared_config) => res,
|
29 |
_ = tokio::signal::ctrl_c() => {
|
|
|
4 |
*/
|
5 |
|
6 |
use aws_config::BehaviorVersion;
|
|
|
7 |
use tokio::select;
|
|
|
8 |
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
9 |
|
10 |
use polyhedron::app;
|
|
|
17 |
.with(EnvFilter::from_default_env())
|
18 |
.init();
|
19 |
|
|
|
|
|
20 |
let shared_config = aws_config::load_defaults(BehaviorVersion::latest()).await;
|
21 |
|
|
|
22 |
select! {
|
23 |
res = app(&shared_config) => res,
|
24 |
_ = tokio::signal::ctrl_c() => {
|
static/index.html
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
<title>Vite + React</title>
|
8 |
-
<script type="module" crossorigin src="/assets/index-
|
9 |
<link rel="stylesheet" href="/assets/index-983f9492.css">
|
10 |
</head>
|
11 |
<body>
|
|
|
5 |
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
<title>Vite + React</title>
|
8 |
+
<script type="module" crossorigin src="/assets/index-f4f6a4b0.js"></script>
|
9 |
<link rel="stylesheet" href="/assets/index-983f9492.css">
|
10 |
</head>
|
11 |
<body>
|
tests/stream_single.rs
CHANGED
@@ -19,7 +19,7 @@ use tracing::{info, error, debug};
|
|
19 |
use polyhedron::{
|
20 |
stream_single,
|
21 |
SingleEvent,
|
22 |
-
asr::
|
23 |
Context
|
24 |
};
|
25 |
|
@@ -51,6 +51,7 @@ async fn test_single() {
|
|
51 |
let url = format!(
|
52 |
"ws://{}/ws/voice?id=123abc&from=zh-CN&to=en-US&voice=Amy", addr
|
53 |
);
|
|
|
54 |
let (mut client_stream, _) = connect_async(url)
|
55 |
.await
|
56 |
.unwrap();
|
@@ -75,8 +76,8 @@ async fn test_single() {
|
|
75 |
|
76 |
let audio_stream = stream! {
|
77 |
for chunk in chunks {
|
78 |
-
yield
|
79 |
-
sleep(Duration::from_millis(
|
80 |
}
|
81 |
};
|
82 |
pin!(audio_stream);
|
@@ -106,7 +107,7 @@ async fn test_single() {
|
|
106 |
assert!(false, "Error: {}", e);
|
107 |
}
|
108 |
}
|
109 |
-
_ = sleep(Duration::from_secs(
|
110 |
assert!(false, "timeout");
|
111 |
}
|
112 |
};
|
|
|
19 |
use polyhedron::{
|
20 |
stream_single,
|
21 |
SingleEvent,
|
22 |
+
asr::slice_i16_to_u8_le,
|
23 |
Context
|
24 |
};
|
25 |
|
|
|
51 |
let url = format!(
|
52 |
"ws://{}/ws/voice?id=123abc&from=zh-CN&to=en-US&voice=Amy", addr
|
53 |
);
|
54 |
+
// let url = "ws://localhost:8080/ws/voice?id=123abc&from=zh-CN&to=en-US&voice=Amy".to_string();
|
55 |
let (mut client_stream, _) = connect_async(url)
|
56 |
.await
|
57 |
.unwrap();
|
|
|
76 |
|
77 |
let audio_stream = stream! {
|
78 |
for chunk in chunks {
|
79 |
+
yield slice_i16_to_u8_le(&chunk);
|
80 |
+
sleep(Duration::from_millis(100)).await;
|
81 |
}
|
82 |
};
|
83 |
pin!(audio_stream);
|
|
|
107 |
assert!(false, "Error: {}", e);
|
108 |
}
|
109 |
}
|
110 |
+
_ = sleep(Duration::from_secs(15)) => {
|
111 |
assert!(false, "timeout");
|
112 |
}
|
113 |
};
|