Decode any media for whisper
(media_data: Arc<[u8]>)
| 312 | |
| 313 | /// Decode any media for whisper |
| 314 | fn decode_audio(media_data: Arc<[u8]>) -> anyhow::Result<Vec<f32>> { |
| 315 | use gst::prelude::*; |
| 316 | |
| 317 | let media_data_len = media_data.len(); |
| 318 | let media_data = Arc::new(Mutex::new(Cursor::new(media_data))); |
| 319 | |
| 320 | let pipeline = |
| 321 | gst::parse::launch(&format!("appsrc name=audio-in stream-type=2 size={media_data_len} ! decodebin ! audioconvert ! audio/x-raw,format=F32LE,channels=1 ! audioresample ! audio/x-raw,rate=16000 ! appsink name=pcm-out sync=false"))? |
| 322 | .dynamic_cast::<gst::Pipeline>().unwrap(); |
| 323 | |
| 324 | pipeline.by_name("audio-in").unwrap().dynamic_cast::<gst_app::AppSrc>().unwrap() |
| 325 | .set_callbacks(gst_app::AppSrcCallbacks::builder() |
| 326 | .need_data({ |
| 327 | let media_data = media_data.clone(); |
| 328 | |
| 329 | move |source, length| { |
| 330 | let mut buffer = vec![0u8; length as _]; |
| 331 | let position = media_data.lock().unwrap().position(); |
| 332 | let _ = media_data.lock().unwrap().read(&mut buffer).unwrap(); |
| 333 | |
| 334 | if position as usize >= media_data_len { |
| 335 | println!("Ending stream"); |
| 336 | source.end_of_stream().unwrap(); |
| 337 | return; |
| 338 | } |
| 339 | |
| 340 | let buffer = gst::Buffer::from_slice(buffer); |
| 341 | let _ = source.push_buffer(buffer); |
| 342 | } |
| 343 | }) |
| 344 | .seek_data({ |
| 345 | let media_data = media_data.clone(); |
| 346 | |
| 347 | move |_, location| { |
| 348 | media_data.lock().unwrap().set_position(location); |
| 349 | |
| 350 | true |
| 351 | } |
| 352 | }) |
| 353 | .build()); |
| 354 | |
| 355 | let pcm_data = Arc::new(Mutex::new(Vec::new())); |
| 356 | |
| 357 | pipeline.by_name("pcm-out").unwrap().dynamic_cast::<gst_app::AppSink>().unwrap() |
| 358 | .set_callbacks(gst_app::AppSinkCallbacks::builder() |
| 359 | .new_sample({ |
| 360 | let pcm_data = pcm_data.clone(); |
| 361 | |
| 362 | move |sink| { |
| 363 | let Ok(sample) = sink.pull_sample() else { return Err(gst::FlowError::Error) }; |
| 364 | |
| 365 | let buffer = sample.buffer().unwrap(); |
| 366 | let mapped_buffer = buffer.map_readable().unwrap(); |
| 367 | |
| 368 | let samples = mapped_buffer.as_slice_of::<f32>().unwrap(); |
| 369 | |
| 370 | pcm_data.lock().unwrap().extend_from_slice(samples); |
| 371 |
no test coverage detected