| 405 | if (WIFSIGNALED(status)) { |
| 406 | return 128 + WTERMSIG(status); |
| 407 | } |
| 408 | throw std::runtime_error("process exited unexpectedly: " + program); |
| 409 | #endif |
| 410 | } |
| 411 | |
| 412 | void run_convert_audio_step( |
| 413 | const engine::io::json::Value & step, |
| 414 | const WorkflowRunOptions & options, |
| 415 | WorkflowContext & context) { |
| 416 | const std::string id = workflow_string(step, "id"); |
| 417 | const auto input = resolve_workflow_path(workflow_string(step, "input"), context); |
| 418 | const auto output = resolve_workflow_path(workflow_string(step, "output"), context); |
| 419 | if (!output.parent_path().empty()) { |
| 420 | std::filesystem::create_directories(output.parent_path()); |
| 421 | } |
| 422 | const int sample_rate = static_cast<int>(workflow_optional_number(step, "sample_rate").value_or(48000.0)); |
| 423 | const int channels = static_cast<int>(workflow_optional_number(step, "channels").value_or(2.0)); |
| 424 | if (sample_rate <= 0 || channels <= 0) { |
| 425 | throw std::runtime_error("convert_audio step requires positive sample_rate and channels"); |
| 426 | } |
| 427 | |
| 428 | std::vector<std::string> args{ |
| 429 | "-y", |
| 430 | "-hide_banner", |
| 431 | "-loglevel", |
| 432 | "error", |
| 433 | }; |
| 434 | if (const auto start = workflow_optional_number(step, "start_seconds")) { |
| 435 | args.push_back("-ss"); |
| 436 | args.push_back(std::to_string(*start)); |
| 437 | } |
| 438 | if (const auto duration = workflow_optional_number(step, "duration_seconds")) { |
| 439 | if (!(*duration > 0.0)) { |
| 440 | throw std::runtime_error("convert_audio duration_seconds must be positive"); |
| 441 | } |
| 442 | args.push_back("-t"); |
| 443 | args.push_back(std::to_string(*duration)); |
| 444 | } |
| 445 | args.push_back("-i"); |
| 446 | args.push_back(path_arg(input)); |
| 447 | args.push_back("-ac"); |
| 448 | args.push_back(std::to_string(channels)); |
| 449 | args.push_back("-ar"); |
| 450 | args.push_back(std::to_string(sample_rate)); |
| 451 | args.push_back(path_arg(output)); |
| 452 | |
| 453 | const int rc = run_process(options.audio_converter, args); |
| 454 | if (rc != 0) { |
| 455 | throw std::runtime_error("convert_audio step failed: " + id); |
| 456 | } |
| 457 | context.values[id + ".audio_path"] = output.string(); |
| 458 | std::cout << "workflow_step=" << id << "\n"; |
no test coverage detected