如何用Python调用FFmpeg检测视频实际音量(解决subprocess报错)
Fixing FFmpeg Volume Detection via Python Subprocess
Hey there! Let's tackle this problem together—detecting valid audio in your downloaded videos using FFmpeg and Python is totally doable, and we can fix those subprocess errors you're seeing.
Why You're Getting Those Errors
First, let's break down the two issues:
- "Output file #0 does not contain any stream": This usually happens when FFmpeg can't properly parse your command (often from passing the command as a single string instead of a list, leading to shell parsing issues) or when the output configuration is misinterpreted.
- "The handle could not be duplicated during redirection": This is a Windows-specific quirk when using
shell=Truewith subprocess handle redirection. Avoidingshell=Trueand properly capturing stderr (where FFmpeg sends its diagnostic output) fixes this.
Working Solution Code
Here's a complete, tested script that runs the FFmpeg volume detection command correctly, captures the output, and extracts the average volume into a variable:
import subprocess import re def get_average_audio_volume(video_file_path): # Build the FFmpeg command as a list (avoids shell parsing errors) ffmpeg_cmd = [ "ffmpeg", "-hide_banner", "-i", video_file_path, "-af", "volumedetect", "-vn", # Disable video stream processing "-f", "null", "-" # Send output to null device ] try: # Run the command, capture stderr (FFmpeg sends logs here, not stdout!) process_result = subprocess.run( ffmpeg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True # Get output as string directly, no need to decode bytes ) # Extract the average volume using regex log_output = process_result.stderr volume_match = re.search(r"mean_volume:\s*(-?\d+\.?\d*)\s*dB", log_output) if volume_match: average_db = float(volume_match.group(1)) return average_db else: print("Couldn't find average volume in FFmpeg's output.") return None except subprocess.CalledProcessError as e: print(f"FFmpeg failed to run: {e.stderr}") return None except Exception as e: print(f"Unexpected error: {str(e)}") return None # Example usage video_path = "testvideo.mp4" avg_volume = get_average_audio_volume(video_path) if avg_volume is not None: print(f"Average audio volume: {avg_volume} dB") # Define your threshold for "valid sound" (adjust as needed) if avg_volume > -60: print("✅ This video has valid audio.") else: print("❌ This video is silent or near-silent.")
Key Notes
- Capture stderr, not stdout: FFmpeg sends all its diagnostic output (including the
volumedetectresults) to stderr, not stdout—this is a common gotcha! - Command as a list: Passing the FFmpeg command as a list of strings avoids shell parsing issues and the handle duplication error on Windows.
- Threshold adjustment: A value around
-91 dBmeans complete silence, but you can adjust the threshold (like-60 dBin the example) based on what counts as "valid sound" for your use case. - FFmpeg availability: Make sure FFmpeg is installed on your system and added to your PATH so Python can find it.
内容的提问来源于stack exchange,提问作者Sreenivasan
相关产品推荐
相关产品推荐

