Skip to content

fix(windows): auto-locate ffmpeg when not in PATH - #1188

Open
jeremy10170 wants to merge 1 commit into
ace-step:mainfrom
jeremy10170:fix/ffmpeg-path-windows
Open

fix(windows): auto-locate ffmpeg when not in PATH#1188
jeremy10170 wants to merge 1 commit into
ace-step:mainfrom
jeremy10170:fix/ffmpeg-path-windows

Conversation

@jeremy10170

@jeremy10170 jeremy10170 commented May 6, 2026

Copy link
Copy Markdown

Problem

On Windows, when ACE-Step is launched via uv run (e.g. from start_gradio_ui.bat), the child Python process sometimes does not inherit the full user PATH. This causes MP3 export to fail with:

RuntimeError: ffmpeg executable not found. Install ffmpeg or add it to PATH to export MP3 files.

This happens even when ffmpeg is installed (via WinGet, Chocolatey, Scoop, or manually) but the binary isn't visible to the subprocess.

Solution

Add a _find_ffmpeg() helper in �udio_utils.py that:

  1. First checks shutil.which('ffmpeg') (standard PATH lookup)
  2. On Windows, falls back to searching common installation locations:
    • WinGet – any Gyan.FFmpeg package version
    • Chocolatey – %ChocolateyInstall%\bin
    • Scoop – %USERPROFILE%\scoop\shims
    • Manual installs – C:\ffmpeg\bin, C:\tools\ffmpeg\bin
  3. Returns the resolved path (or raises FileNotFoundError with an actionable message linking to ffmpeg.org)

The MP3 save code now calls _find_ffmpeg() instead of hardcoding 'ffmpeg'.

Testing

Reproduced on Windows 11 with ffmpeg installed via WinGet (winget install Gyan.FFmpeg) and ACE-Step launched through start_gradio_ui.bat. MP3 export now succeeds.

Summary by CodeRabbit

  • Bug Fixes
    • Improved MP3 export functionality on Windows systems with better FFmpeg detection
    • Enhanced error messages when FFmpeg is unavailable, providing helpful guidance and download information

Add _find_ffmpeg() helper that searches common Windows installation
locations (WinGet, Chocolatey, Scoop, manual installs) before falling
back to a FileNotFoundError with an actionable message.

This fixes MP3 export failing with "ffmpeg executable not found" for
users who installed ffmpeg via WinGet or other package managers that
don't always inject the binary into the PATH of child processes
spawned by uv.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR adds Windows-compatible FFmpeg discovery to the audio utilities module by introducing a helper function that locates FFmpeg via PATH, Windows package managers (WinGet, Chocolatey, Scoop), and common installation directories. The MP3 export function now uses this discovered path and provides improved error messages if FFmpeg is not found.

Changes

FFmpeg Discovery and Integration

Layer / File(s) Summary
Imports
acestep/audio_utils.py (lines 16–17)
Added shutil and sys imports to support subprocess invocation and platform detection.
FFmpeg Discovery Logic
acestep/audio_utils.py (lines 27–63)
New internal _find_ffmpeg() function searches PATH, Windows package managers (WinGet, Chocolatey, Scoop), and common installation directories to locate the FFmpeg executable.
MP3 Export Integration
acestep/audio_utils.py (lines 208–223)
Updated _save_mp3() to call _find_ffmpeg() and use the discovered path in command construction. Enhanced error handling provides a detailed RuntimeError with a download URL when FFmpeg is not found.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


In Windows lands where paths are long,
A rabbit found where FFmpeg belongs,
Through package managers and folders deep,
We hunt the treasure, the journey's sweet! 🐰✨

🚥 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 describes the main change: adding Windows-compatible ffmpeg discovery when not in PATH, which matches the core objective and file changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

@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.

Actionable comments posted: 1

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)

200-223: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

FileNotFoundError from torchaudio.save() will be misreported as "ffmpeg not found".

torchaudio.save() (line 201) runs inside the same try block that catches FileNotFoundError and re-raises it as "ffmpeg executable not found". If the soundfile backend, a missing codec, or a temp-directory eviction raises FileNotFoundError, the real cause is silently replaced with a misleading ffmpeg message, making the failure undiagnosable in the field.

Move _find_ffmpeg() before the try block so the ffmpeg FileNotFoundError is propagated cleanly and torchaudio.save() errors surface with their own messages.

🐛 Proposed fix
+        ffmpeg_exe = _find_ffmpeg()   # fail fast before writing the temp WAV
         with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_wav:
             temp_wav_path = Path(temp_wav.name)

         try:
             torchaudio.save(
                 str(temp_wav_path),
                 tensor_to_save,
                 int(target_sample_rate),
                 channels_first=True,
                 backend='soundfile',
             )
-            ffmpeg_exe = _find_ffmpeg()
             cmd = [
                 ffmpeg_exe, '-y', '-hide_banner', '-loglevel', 'error',
🤖 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 200 - 223, Move the ffmpeg lookup out of
the broad try so a FileNotFoundError raised by torchaudio.save() isn't
misattributed to ffmpeg; call _find_ffmpeg() (assign to ffmpeg_exe) before
entering the try block, then use a narrower try/except around subprocess.run (or
catch FileNotFoundError only for the ffmpeg invocation) to re-raise the helpful
"ffmpeg executable not found" RuntimeError; update the block containing
torchaudio.save, subprocess.run, and logger.debug accordingly so torchaudio.save
errors surface with their original messages and only subprocess.run's
FileNotFoundError is converted.
🤖 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.

Inline comments:
In `@acestep/audio_utils.py`:
- Around line 27-28: Update the _find_ffmpeg function docstring to include
explicit Returns and Raises sections: state that it returns a str path to the
ffmpeg executable when found and that it raises FileNotFoundError if ffmpeg
cannot be located; keep the existing short description about checking PATH and
common Windows install locations and mention the exception is raised
unconditionally when not found so callers can rely on it.

---

Outside diff comments:
In `@acestep/audio_utils.py`:
- Around line 200-223: Move the ffmpeg lookup out of the broad try so a
FileNotFoundError raised by torchaudio.save() isn't misattributed to ffmpeg;
call _find_ffmpeg() (assign to ffmpeg_exe) before entering the try block, then
use a narrower try/except around subprocess.run (or catch FileNotFoundError only
for the ffmpeg invocation) to re-raise the helpful "ffmpeg executable not found"
RuntimeError; update the block containing torchaudio.save, subprocess.run, and
logger.debug accordingly so torchaudio.save errors surface with their original
messages and only subprocess.run's FileNotFoundError is converted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 653a58ec-48dc-43e0-86cd-5db92680d88d

📥 Commits

Reviewing files that changed from the base of the PR and between 6c1b2ef and 0e3cab6.

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

Comment thread acestep/audio_utils.py
Comment on lines +27 to +28
def _find_ffmpeg() -> str:
"""Locate the ffmpeg executable, checking common installation paths on Windows if not in PATH."""

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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Docstring is missing Returns and Raises sections.

Per coding guidelines, docstrings must include purpose, key inputs/outputs, and raised exceptions when relevant. _find_ffmpeg unconditionally raises FileNotFoundError when the executable is absent, which callers rely on.

✏️ Proposed docstring update
-    """Locate the ffmpeg executable, checking common installation paths on Windows if not in PATH."""
+    """Locate the ffmpeg executable, checking common installation paths on Windows if not in PATH.
+
+    Returns:
+        Absolute path to the ffmpeg executable as a string.
+
+    Raises:
+        FileNotFoundError: If ffmpeg cannot be found via PATH or any known install location.
+    """

As per coding guidelines, "Docstrings are mandatory for all new or modified Python modules, classes, and functions. Docstrings must be concise and include purpose plus key inputs/outputs and raised exceptions when relevant."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _find_ffmpeg() -> str:
"""Locate the ffmpeg executable, checking common installation paths on Windows if not in PATH."""
def _find_ffmpeg() -> str:
"""Locate the ffmpeg executable, checking common installation paths on Windows if not in PATH.
Returns:
Absolute path to the ffmpeg executable as a string.
Raises:
FileNotFoundError: If ffmpeg cannot be found via PATH or any known install location.
"""
🤖 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 27 - 28, Update the _find_ffmpeg
function docstring to include explicit Returns and Raises sections: state that
it returns a str path to the ffmpeg executable when found and that it raises
FileNotFoundError if ffmpeg cannot be located; keep the existing short
description about checking PATH and common Windows install locations and mention
the exception is raised unconditionally when not found so callers can rely on
it.

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.

1 participant