ATH-MaaS/Pixelle-Video · error · RuntimeError

Failed to concatenate videos: {error_msg}

Error message

Failed to concatenate videos: {error_msg}

What it means

_concat_demuxer runs ffmpeg with the concat demuxer (-f concat -safe 0 -i filelist). If the ffmpeg subprocess fails, ffmpeg-python raises ffmpeg.Error, and this handler wraps its stderr into a RuntimeError with the 'Failed to concatenate videos' prefix. The actual cause is in the captured FFmpeg stderr text.

Source

Thrown at pixelle_video/services/video.py:203

                escaped_path = str(abs_path).replace("'", "'\\''")
                f.write(f"file '{escaped_path}'\n")
            filelist = f.name
        
        try:
            logger.debug(f"Created filelist: {filelist}")
            (
                ffmpeg
                .input(filelist, format='concat', safe=0)
                .output(output, c='copy')
                .overwrite_output()
                .run(capture_stdout=True, capture_stderr=True)
            )
            logger.success(f"Videos concatenated successfully: {output}")
            return output
        except ffmpeg.Error as e:
            error_msg = e.stderr.decode() if e.stderr else str(e)
            logger.error(f"FFmpeg concat error: {error_msg}")
            raise RuntimeError(f"Failed to concatenate videos: {error_msg}")
        finally:
            if os.path.exists(filelist):
                os.unlink(filelist)
    
    def _concat_filter(self, videos: List[str], output: str) -> str:
        """
        Concatenate using concat filter (slower but handles different formats)
        
        FFmpeg equivalent:
            ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]"
                   -map "[v]" -map "[a]" output.mp4
        """
        try:
            # Build filter_complex string manually
            n = len(videos)
            
            # Build input stream labels: [0:v][0:a][1:v][1:a]...
            stream_spec = "".join([f"[{i}:v][{i}:a]" for i in range(n)])

View on GitHub (pinned to 848b054e4f)

Solutions

  1. Read the FFmpeg stderr in the exception message — it names the failing input or codec issue.
  2. Verify every path in `videos` exists and is a valid, readable media file (`ffprobe` each one).
  3. Ensure all inputs share codec, resolution, and timebase, or force re-encoding (the concat filter path) instead of the stream-copy demuxer.
  4. Re-encode/re-export problem inputs to a uniform format (e.g. h264/aac mp4) before concatenating.

Example fix

// before
service.concat_videos(['a.mp4', 'b.webm'], 'out.mp4')  # demuxer fails: codec mismatch
// after
# normalize inputs first, then concat
for f in ['a.mp4', 'b.webm']:
    normalize_to_h264_mp4(f)
service.concat_videos(['a.mp4', 'b.mp4'], 'out.mp4')
Defensive patterns

Strategy: try-catch

Validate before calling

for v in videos:
    assert os.path.isfile(v), f'missing input: {v}'
    import ffmpeg as ff
    info = ff.probe(v)
    assert info['streams'], f'no streams in {v}'

Type guard

def is_valid_media(path: str) -> bool:
    try:
        return bool(ffmpeg.probe(path).get('streams'))
    except Exception:
        return False

Try / catch

try:
    service.concat_videos(videos, out)
except RuntimeError as e:
    if 'Failed to concatenate videos' in str(e):
        logger.error(f'ffmpeg concat demuxer failed: {e}')
        # inspect stderr in message; re-encode inputs or fall back to filter concat
    else:
        raise

Prevention

When it happens

Trigger: Files listed in the filelist do not exist or are unreadable; inputs have mismatched codecs/resolutions/timebases that the demuxer cannot concat; `-safe 0` omitted for absolute paths (not in this implementation, but path quoting issues); corrupted or non-media files passed as inputs.

Common situations: Concatenating clips from different sources/encoders; a temp segment was deleted before concatenation; files with non-ASCII paths mishandled; codec mismatch (h264 vs vp9) requiring re-encode via the filter method instead.

Related errors


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