Skip to content

Fixed 'torchcodec' not supported issue on XPU and ROCm when calling torchaudio.save - #1242

Open
fisheryv wants to merge 3 commits into
ace-step:mainfrom
fisheryv:main
Open

Fixed 'torchcodec' not supported issue on XPU and ROCm when calling torchaudio.save#1242
fisheryv wants to merge 3 commits into
ace-step:mainfrom
fisheryv:main

Conversation

@fisheryv

@fisheryv fisheryv commented Jun 12, 2026

Copy link
Copy Markdown

In torchaudio 2.9+ and later versions, torchaudio.save() internally calls save_with_torchcodec, even if the backend='soundfile' or backend='ffmpeg' parameter is specified, which will be ignored. See https://docs.pytorch.org/audio/stable/generated/torchaudio.save.html#torchaudio.save. When torchcodec is not installed (e.g., XPU and ROCm do not support torchcodec), this results in an ImportError: TorchCodec is required for save_with_torchcodec or ModuleNotFoundError: No module named 'torchcodec'.

I implemented a dual-path compatibility scheme with torchcodec as the priority and soundfile/ffmpeg as fallbacks, to address the issue where XPU and ROCm do not support torchcodec, or torchcodec incompatibility prevents saving generated audio.

Related issues: #665

Summary by CodeRabbit

  • Bug Fixes

    • Improved audio export reliability with smarter backend routing: uses the torchaudio path when available, otherwise falls back to soundfile/ffmpeg.
    • Added stronger handling for WAV32 and clearer fallback behavior for non-MP3 formats, while keeping MP3 handling consistent.
    • Hardened the export flow to recover when torchaudio saving fails.
  • Tests

    • Expanded coverage for torchcodec detection, per-format backend selection, codec mappings, filename extension behavior, and fallback routing.
    • Updated/isolated mocks to verify ffmpeg/soundfile behavior across execution paths.

…th torchcodec as the priority and soundfile/ffmpeg as fallbacks, to address the issue where XPU and ROCm do not support torchcodec, or torchcodec incompatibility prevents saving generated audio.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds runtime torchcodec detection and dual-path audio export. Saves use torchaudio when available and soundfile/ffmpeg otherwise, with format-specific fallbacks, expanded backend tests, and hardened smoke-test WAV export.

Changes

Audio Export Backend Selection and Fallback Pipeline

Layer / File(s) Summary
Torchcodec availability detection
acestep/audio_utils.py, acestep/audio_utils_test.py
Caches torchcodec availability at import time and tests detection failure handling.
Soundfile and ffmpeg fallback helpers
acestep/audio_utils.py
Adds FLOAT WAV writing, ffmpeg transcoding, subprocess error handling, and temporary-file cleanup.
Dual-path format dispatch
acestep/audio_utils.py
Routes formats through torchaudio or soundfile/ffmpeg, with format-specific fallback behavior and MP3 error handling.
Backend routing and format validation
acestep/audio_utils_test.py
Tests codec selection, extensions, backend routing, fallback behavior, and related format coverage.
Smoke-test audio save fallback
scripts/flow_edit_overlay_smoke.py
Falls back from torchaudio WAV export to soundfile FLOAT WAV output when saving fails.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: ChuxiJ

Poem

🐰 Torches hop along the track,

Soundfiles catch the moments back.
ffmpeg hums a codec tune,
WAVs bloom bright beneath the moon.
Every format finds its way! 🎵

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding a torchcodec-aware fallback path for torchaudio.save on XPU/ROCm.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
acestep/audio_utils.py (1)

437-458: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fallback handler will fail for opus/aac formats.

If _save_via_ffmpeg fails for opus/aac (e.g., ffmpeg not found), the exception handler at line 437 catches it and attempts sf.write(..., format=format.upper()) where format is "OPUS" or "AAC". However, soundfile does not support these formats—it will raise ValueError: Unknown format or similar, masking the original ffmpeg error.

Consider re-raising immediately for formats that soundfile cannot handle:

🐛 Proposed fix
         except Exception as e:
             if format == "mp3":
                 logger.error(f"[AudioSaver] MP3 export failed without fallback: {e}")
                 raise
+            if format in ["opus", "aac"]:
+                logger.error(f"[AudioSaver] {format.upper()} export failed (ffmpeg required): {e}")
+                raise
             try:
                 import soundfile as sf
                 audio_np = audio_tensor.transpose(0, 1).numpy()  # -> [samples, channels]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@acestep/audio_utils.py` around lines 437 - 458, The fallback path in the
except block after _save_via_ffmpeg attempts to call soundfile for formats it
doesn't support (e.g., "opus" or "aac"), which masks the original ffmpeg error;
update the handler in the except Exception as e: block to check format.lower()
and if it's an unsupported soundfile format (at minimum "opus" and "aac")
immediately log and re-raise the original exception `e` instead of trying
sf.write; otherwise proceed with the existing soundfile fallback logic that
transposes audio_tensor and calls sf.write.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@acestep/audio_utils.py`:
- Around line 437-458: The fallback path in the except block after
_save_via_ffmpeg attempts to call soundfile for formats it doesn't support
(e.g., "opus" or "aac"), which masks the original ffmpeg error; update the
handler in the except Exception as e: block to check format.lower() and if it's
an unsupported soundfile format (at minimum "opus" and "aac") immediately log
and re-raise the original exception `e` instead of trying sf.write; otherwise
proceed with the existing soundfile fallback logic that transposes audio_tensor
and calls sf.write.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 45f1de59-be6b-42b0-8808-dc9008558f1e

📥 Commits

Reviewing files that changed from the base of the PR and between dce6214 and f60e637.

📒 Files selected for processing (3)
  • acestep/audio_utils.py
  • acestep/audio_utils_test.py
  • scripts/flow_edit_overlay_smoke.py

@mnj

mnj commented Jun 20, 2026

Copy link
Copy Markdown

This solved the issue here, where I otherwise had zero progress on getting it working:

Arch Linux / 20GB AMD 7900 XT

Followed https://github.com/ace-step/ACE-Step-1.5/blob/main/docs/en/ACE-Step1.5-Rocm-Manual-Linux.md
But used rocm 7.2 version of pytorch
This patch to get it to generate the mp3s.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
acestep/audio_utils.py (1)

43-51: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Close the temp file before probing torchaudio.save (acestep/audio_utils.py:43-51)
In torchaudio 2.9, backend="soundfile" is ignored, so this probe still runs through the torchcodec-backed save path while the NamedTemporaryFile handle is open. On Windows that can raise PermissionError/OSError and make acestep.audio_utils unimportable. Use delete=False (or a temp dir), close the file before saving, and broaden the exception handling here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@acestep/audio_utils.py` around lines 43 - 51, Update the torchaudio
availability probe to create the temporary WAV with delete=False, close the
NamedTemporaryFile before calling torchaudio.save, and remove the temporary file
afterward (preferably in a finally block). Broaden the probe’s exception
handling to include OSError/PermissionError and other relevant save failures so
importing acestep.audio_utils cannot fail due to platform-specific
temporary-file or backend errors.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@acestep/audio_utils.py`:
- Around line 43-51: Update the torchaudio availability probe to create the
temporary WAV with delete=False, close the NamedTemporaryFile before calling
torchaudio.save, and remove the temporary file afterward (preferably in a
finally block). Broaden the probe’s exception handling to include
OSError/PermissionError and other relevant save failures so importing
acestep.audio_utils cannot fail due to platform-specific temporary-file or
backend errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c846250c-441a-4067-8aa2-74a8171027b8

📥 Commits

Reviewing files that changed from the base of the PR and between f60e637 and a5632cd.

📒 Files selected for processing (2)
  • acestep/audio_utils.py
  • acestep/audio_utils_test.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants