| 439 | const engine::audio::VadAudioChunkOptions & options) { |
| 440 | if (audio.channels <= 0) { |
| 441 | throw std::runtime_error("VAD chunk planning requires positive audio channels"); |
| 442 | } |
| 443 | if (audio.samples.size() % static_cast<size_t>(audio.channels) != 0) { |
| 444 | throw std::runtime_error("VAD chunk planning requires audio samples divisible by channel count"); |
| 445 | } |
| 446 | const int64_t audio_frames = static_cast<int64_t>(audio.samples.size() / static_cast<size_t>(audio.channels)); |
| 447 | const auto chunks = engine::audio::plan_vad_audio_chunks(result.speech_segments, audio_frames, options); |
| 448 | if (!path.parent_path().empty()) { |
| 449 | std::filesystem::create_directories(path.parent_path()); |
| 450 | } |
| 451 | std::ofstream(path) << vad_chunks_to_json(chunks); |
| 452 | std::cout << "vad_chunks_out=" << path.string() << "\n"; |
| 453 | } |
| 454 | |
| 455 | void run_streaming( |
| 456 | int argc, |
| 457 | char ** argv, |
| 458 | engine::runtime::IStreamingVoiceTaskSession & streaming, |
| 459 | engine::runtime::IVoiceTaskSession & session, |
| 460 | engine::runtime::TaskRequest & request) { |
| 461 | const auto out_dir = minitts::cli::optional_path_arg(argc, argv, "--out-dir"); |
| 462 | const auto result = minitts::app::run_streaming_task( |
| 463 | streaming, |
| 464 | request, |
| 465 | [&](const engine::runtime::StreamEvent & event) { |
| 466 | if (event.partial_text.has_value()) { |
| 467 | std::cout << "partial_text=" << event.partial_text->text << "\n"; |
| 468 | } |
| 469 | engine::runtime::TaskResult event_result; |
| 470 | event_result.audio_output = event.audio_output; |
| 471 | event_result.named_audio_outputs = event.named_audio_outputs; |
| 472 | event_result.speaker_turns = event.speaker_turns; |
| 473 | event_result.word_timestamps = event.word_timestamps; |
| 474 | event_result.output_artifacts = event.output_artifacts; |
| 475 | minitts::app::emit_task_result( |
| 476 | event_result, |
| 477 | std::nullopt, |
| 478 | out_dir, |
| 479 | out_dir, |
| 480 | std::nullopt, |
| 481 | std::nullopt, |
| 482 | std::nullopt); |
| 483 | for (const auto & activity : event.voice_activity) { |
| 484 | std::cout << "event="; |
| 485 | switch (activity.kind) { |
| 486 | case engine::runtime::VoiceActivityEvent::Kind::SpeechStart: |
| 487 | std::cout << "speech_start"; |
| 488 | break; |
| 489 | case engine::runtime::VoiceActivityEvent::Kind::SpeechEnd: |
| 490 | std::cout << "speech_end"; |
| 491 | break; |
| 492 | case engine::runtime::VoiceActivityEvent::Kind::SpeechSegment: |
| 493 | std::cout << "speech_segment"; |
| 494 | break; |
| 495 | } |
| 496 | std::cout << " sample=" << activity.sample << " probability=" << activity.probability << "\n"; |
| 497 | } |
| 498 | }); |
no test coverage detected