audio.mix
Operation: audio.mix
Category: media
Tags: ffmpeg, audio, mix
Mix voiceover audio with background music at configurable volume
Runtime
Section titled “Runtime”Type: Native (built-in)
Timeout: 300s
Retries: 3 (ExponentialWithJitter)
Inputs
Section titled “Inputs”| Name | Type | Required | Default | Description |
|---|---|---|---|---|
voiceover_url | Asset | Yes | — | Voiceover audio URL/path |
bgm_url | Asset | No | — | Background music URL/path |
Outputs
Section titled “Outputs”| Name | Type | Description |
|---|---|---|
url | Asset | Mixed audio URL |
path | String | Local file path |
bgm_mixed | Boolean | Whether BGM was mixed in |
Default Configuration
Section titled “Default Configuration”{ "bgm_volume": 0.15}The bgm_volume parameter is overridable as a workflow-level input variable, so users can adjust per-run:
fab-workflow video/ai-shorts --input topic="..." --input bgm_volume=0.20SDK Stage (v0.2.0)
Section titled “SDK Stage (v0.2.0)”from fabric_workflow_sdk.stages.audio import mix_audio, remix_ducked
mixed = await mix_audio({"voiceover_path": "vo.mp3", "bgm_path": "bgm.mp3", "bgm_volume": 0.20})ducked = await remix_ducked({**mixed, "transcript": [...]})Niche-Aware Ducking
Section titled “Niche-Aware Ducking”The bgm_volume parameter controls how much background music is ducked when voiceover is playing. Different content niches benefit from different levels:
| Niche | Suggested bgm_volume | Rationale |
|---|---|---|
| Tech / Education | 0.10 | Prioritize voice clarity for information-dense content |
| Default | 0.15 | Balanced — audible music without competing with voice |
| Comedy / Entertainment | 0.20–0.25 | Music adds energy and comedic timing |
In workflow YAML definitions, promote bgm_volume to a workflow-level input variable so callers can override per-run:
input: bgm_volume: 0.15
nodes: mix-audio: op: audio.mix params: { bgm_volume: "{{bgm_volume}}" }import { WorkflowBuilder } from "@fabric-platform/sdk";
const workflow = new WorkflowBuilder("my-workflow") .node("audio-mix", "tool", (n) => n.config({ operation: "audio.mix", // ... node-specific config }) ) .build();from fabric_platform import FabricClient
fabric = FabricClient(api_key="fab_xxx")
wf_id = fabric.upsert_workflow("my-workflow", nodes=[ { "key": "audio-mix", "kind": "tool", },])use fabric_sdk::FabricClient;
let client = FabricClient::new("https://gofabric.dev", api_key)?;
let wf_id = client.upsert_workflow("my-workflow", serde_json::json!({ "nodes": [{ "key": "audio-mix", "kind": "tool" }]})).await?;curl -X POST https://gofabric.dev/v1/workflow-definitions \ -H "Authorization: Bearer $FABRIC_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "my-workflow", "nodes": [{ "key": "audio-mix", "kind": "tool" }] }'