在Django中用FFmpeg转WAV音频片段为FLAC时遇时长参数错误
Hey there! Let's break down why you're hitting that "Invalid duration specification for ss" error and get your FLAC conversion working properly.
What's Causing the Error?
Looking at your failed FFmpeg command, the issue is clear: you're passing entire lists of timestamps as strings to the -ss (start time) and -t (duration) parameters. FFmpeg can't parse something like [(0.006000000000000005, 1.03), ...] as a valid timestamp—it expects a single numerical value (like 0.006) for each parameter.
On top of that, your logic for adjusting start/end times was applying the padding to the entire list incorrectly, instead of processing each (start, end) pair individually.
Corrected FLACConverter Class
Here's a revised version of your class that fixes these issues, handles multiple segments properly, and cleans up temporary files safely:
import os import tempfile import subprocess from pathlib import Path class FLACConverter(object): # pylint: disable=too-few-public-methods """ Class for converting regions of an input audio file into a single FLAC audio file """ def __init__(self, source_path, include_before=0.25, include_after=0.25): self.source_path = source_path self.include_before = include_before self.include_after = include_after def __call__(self, regions): try: print("Regions to convert to FLAC: {}".format(regions)) temp_segment_files = [] # Process each audio segment one by one for orig_start, orig_end in regions: # Adjust timestamps with padding (ensure start doesn't go below 0) adjusted_start = max(0.0, orig_start - self.include_before) adjusted_end = orig_end + self.include_after segment_duration = adjusted_end - adjusted_start # Create a temporary file for this segment temp_file = tempfile.NamedTemporaryFile(suffix='.flac', delete=False) temp_segment_files.append(temp_file.name) temp_file.close() # Build valid FFmpeg command for the segment ffmpeg_cmd = [ "ffmpeg", "-ss", str(adjusted_start), # Single valid start timestamp "-t", str(segment_duration), # Single valid duration value "-y", "-i", self.source_path, "-loglevel", "error", temp_file.name ] # Execute the conversion subprocess.check_output(ffmpeg_cmd, shell=os.name == "nt") # Merge multiple segments into one FLAC file if needed if len(temp_segment_files) > 1: # Create a concat list file for FFmpeg concat_list_file = tempfile.NamedTemporaryFile(suffix='.txt', delete=False) with open(concat_list_file.name, 'w') as f: for seg_file in temp_segment_files: f.write(f"file '{Path(seg_file).resolve()}'\n") # Merge segments using FFmpeg's concat demuxer (lossless for FLAC) final_temp_file = tempfile.NamedTemporaryFile(suffix='.flac', delete=False) concat_cmd = [ "ffmpeg", "-f", "concat", "-safe", "0", "-i", concat_list_file.name, "-y", "-loglevel", "error", final_temp_file.name ] subprocess.check_output(concat_cmd, shell=os.name == "nt") # Clean up intermediate files os.unlink(concat_list_file.name) for seg_file in temp_segment_files: os.unlink(seg_file) # Read the merged FLAC data with open(final_temp_file.name, 'rb') as f: flac_data = f.read() os.unlink(final_temp_file.name) else: # Only one segment, read directly with open(temp_segment_files[0], 'rb') as f: flac_data = f.read() os.unlink(temp_segment_files[0]) print("Successfully processed audio regions to FLAC") return flac_data except KeyboardInterrupt: # Clean up temp files if user interrupts for file_path in temp_segment_files: if os.path.exists(file_path): os.unlink(file_path) return None except subprocess.CalledProcessError as e: print(f"FFmpeg failed with error: {e}") # Clean up temp files on failure for file_path in temp_segment_files: if os.path.exists(file_path): os.unlink(file_path) return None
Key Improvements
- Per-segment processing: We loop through each (start, end) pair in your regions list, generating a valid FFmpeg command for each segment.
- Valid timestamp parameters: Each
-ssand-tgets a single numerical value (in seconds) that FFmpeg can parse correctly. - Segment merging: If you have multiple regions, we use FFmpeg's concat demuxer to merge them into a single FLAC file (this is lossless for FLAC, so no quality loss).
- Safe cleanup: All temporary files are deleted even if the process is interrupted or fails, preventing leftover files from cluttering your system.
How to Use It
Just call the converter with your regions list like before:
converter = FLACConverter("path/to/your/audio.wav") flac_data = converter([(0.006, 1.03), (2.054, 4.87)])
The returned flac_data is the binary content of the merged FLAC file, which you can save or use as needed.
内容的提问来源于stack exchange,提问作者maryam mehboob

