ATH-MaaS/Pixelle-Video · error · Exception

No audio file generated by workflow

Error message

No audio file generated by workflow

What it means

Even when the TTS workflow completes, _call_comfyui_workflow must find an audio file. It probes result.audios, then result.files, then scans result.outputs for strings ending in .mp3/.wav/.flac. If none yields a path it raises 'No audio file generated by workflow' after dumping the full result to logs. This indicates a completed run with no recognizable audio output.

Source

Thrown at pixelle_video/services/tts_service.py:292

                logger.debug(f"✅ Found audio in result.files: {audio_path}")
            # Check in outputs dictionary
            elif hasattr(result, 'outputs') and result.outputs:
                logger.debug(f"Searching for audio file in result.outputs: {result.outputs}")
                # Try to find audio file in outputs
                for key, value in result.outputs.items():
                    if isinstance(value, str) and any(value.endswith(ext) for ext in ['.mp3', '.wav', '.flac']):
                        audio_path = value
                        logger.debug(f"✅ Found audio in result.outputs[{key}]: {audio_path}")
                        break
            
            if not audio_path:
                logger.error("No audio file generated")
                logger.error(f"❌ Result analysis:")
                logger.error(f"   - result.audios: {getattr(result, 'audios', 'NOT_FOUND')}")
                logger.error(f"   - result.files: {getattr(result, 'files', 'NOT_FOUND')}")
                logger.error(f"   - result.outputs: {getattr(result, 'outputs', 'NOT_FOUND')}")
                logger.error(f"   - Full __dict__: {result.__dict__}")
                raise Exception("No audio file generated by workflow")
            
            # If output_path provided and audio_path is URL, download to local
            if output_path and audio_path.startswith(('http://', 'https://')):
                import httpx
                import os
                
                # Ensure parent directory exists
                os.makedirs(os.path.dirname(output_path), exist_ok=True)
                
                logger.info(f"Downloading audio from {audio_path} to {output_path}")
                async with httpx.AsyncClient() as client:
                    response = await client.get(audio_path)
                    response.raise_for_status()
                    
                    with open(output_path, 'wb') as f:
                        f.write(response.content)
                
                logger.info(f"✅ Generated audio (ComfyUI): {output_path}")

View on GitHub (pinned to 848b054e4f)

Solutions

  1. Check the logged 'Result analysis' block (result.audios/files/outputs and full __dict__) to see exactly where the audio landed; adapt extraction to that shape.
  2. Ensure the workflow has an enabled audio output node and that RunningHub exposes it as an output file.
  3. If the audio is saved with another extension (.ogg, .opus), extend the outputs scan's extension list or normalize the workflow to emit .mp3/.wav.
  4. If outputs nest the URL inside a dict, update extraction to unwrap the value (e.g. value['url']) instead of requiring a bare string.
  5. Upgrade ComfyKit if your version predates first-class audios support in its result object.

Example fix

// before
for key, value in result.outputs.items():
    if isinstance(value, str) and any(value.endswith(ext) for ext in ['.mp3', '.wav', '.flac']):
        audio_path = value
// after
AUDIO_EXTS = ('.mp3', '.wav', '.flac', '.ogg', '.opus')
for key, value in result.outputs.items():
    if isinstance(value, dict):
        value = value.get('url') or value.get('path')
    if isinstance(value, str) and value.endswith(AUDIO_EXTS):
        audio_path = value
        break
Defensive patterns

Strategy: type-guard

Validate before calling

# pre-flight: workflow must have an enabled audio output node
def workflow_produces_audio(workflow_json: dict) -> bool:
    nodes = workflow_json.get("nodes", [])
    return any("SaveAudio" in n.get("type", "") or "AudioCombine" in n.get("type", "")
               for n in nodes if not n.get("mode"))
assert workflow_produces_audio(load_workflow(tts_workflow_key))

Type guard

def extract_audio_path(result) -> str | None:
    audios = getattr(result, "audios", None)
    if audios:
        return audios[0]
    files = getattr(result, "files", None)
    if files:
        return files[0]
    for v in (getattr(result, "outputs", None) or {}).values():
        if isinstance(v, dict):
            v = v.get("url") or v.get("path")
        if isinstance(v, str) and v.endswith((".mp3", ".wav", ".flac", ".ogg", ".opus")):
            return v
    return None

Try / catch

try:
    audio = await tts_service(...)
except Exception as e:
    if "No audio file generated" in str(e):
        logger.error("TTS workflow produced no audio; inspect output node config and result schema")
        raise WorkflowConfigError("TTS workflow has no recognizable audio output") from e
    raise

Prevention

When it happens

Trigger: result.status == 'completed' but result.audios, result.files are empty/missing and result.outputs contains no string ending in .mp3/.wav/.flac — e.g. the workflow saves audio under a different extension (.ogg, .opus), the audio save node is bypassed, or outputs are nested dicts rather than plain strings.

Common situations: TTS node writes non-standard formats the extension scan misses; ComfyKit version whose result schema stores audio elsewhere (e.g. result.outputs['audio'] as a dict with 'url' key); RunningHub workflow without an exposed audio output node; SaveAudio node disabled in the graph.

Related errors


AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30). Data as JSON: /api/errors/b38586239b08bc26. Report an issue: GitHub.