harry0703/MoneyPrinterTurbo · error · BgmUploadError

background music file exceeds the 30 MB limit

Error message

background music file exceeds the 30 MB limit

What it means

Raised during staged copying of a background music upload when the cumulative byte count exceeds MAX_BGM_UPLOAD_BYTES (30 MB, app/services/bgm.py:16). The check happens per 1 MB chunk before writing, so at most one chunk over the limit hits disk; the temp file is then removed via _remove_staged_file and a BgmUploadError propagates. This is a server-side cap so oversized files never fully hit disk and compete with video task I/O.

Source

Thrown at app/services/bgm.py:207

            raise BgmUploadError("background music upload is not seekable") from exc

        # 保留原始扩展名便于 FFmpeg 针对无容器头的 AAC 等格式选择正确的
        # demuxer;临时文件仍放在目标目录,以保证最终 os.replace 是原子操作。
        descriptor, temp_path = tempfile.mkstemp(
            prefix=_INTERNAL_UPLOAD_PREFIX,
            suffix=Path(safe_name).suffix.lower(),
            dir=target_dir,
        )
        with os.fdopen(descriptor, "wb") as output:
            while True:
                chunk = source.read(_COPY_CHUNK_BYTES)
                if not chunk:
                    break
                if not isinstance(chunk, (bytes, bytearray, memoryview)):
                    raise BgmUploadError("background music upload must be binary")
                total_bytes += len(chunk)
                if total_bytes > MAX_BGM_UPLOAD_BYTES:
                    raise BgmUploadError("background music file exceeds the 30 MB limit")
                output.write(chunk)
            output.flush()
            os.fsync(output.fileno())

        if total_bytes == 0:
            raise BgmUploadError("background music file is empty")
        return safe_name, temp_path, total_bytes
    except Exception as exc:
        _remove_staged_file(temp_path)
        if isinstance(exc, BgmUploadError):
            raise
        if isinstance(exc, OSError):
            raise BgmServiceError("failed to stage background music upload") from exc
        raise
    finally:
        # Streamlit 还需要使用同一个 UploadedFile 做浏览器试听;恢复文件指针可
        # 避免校验后播放器或最终保存读取到空内容。
        try:

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Compress or trim the audio to under 30 MB (convert WAV/FLAC to MP3/AAC/OGG, or cut the clip to the video length).
  2. Enforce the same limit client-side (Streamlit file_uploader type + a size check) so users get feedback before the upload starts.
  3. If 30 MB is genuinely too small for your content, re-encode to a lossy format first rather than raising MAX_BGM_UPLOAD_BYTES, since the cap also protects disk and I/O.

Example fix

// before (client sends 45 MB WAV)

// after: re-encode before upload
ffmpeg -i input.wav -b:a 192k output.mp3  # ~13 MB for 10 min
Defensive patterns

Strategy: validation

Validate before calling

MAX = 30 * 1024 * 1024
size = os.fseek(fh, 0, os.SEEK_END) and os.fstat(fh.fileno()).st_size or fh.seek(0)
if os.fstat(fh.fileno()).st_size > MAX:
    raise ClientError('file too large; compress to under 30 MB')

Try / catch

try:
    stage_bgm_upload(fh, filename)
except BgmUploadError as e:
    if 'exceeds the 30 MB' in str(e):
        show_user('Compress the audio (e.g. convert WAV to MP3) and retry')

Prevention

When it happens

Trigger: Uploading any BGM file larger than 30*1024*1024 bytes through the WebUI or API staging path (e.g. a 40 MB WAV or FLAC). The error fires as soon as total_bytes crosses the limit mid-stream, not after the full write.

Common situations: Uncompressed WAV/FLAC rips easily exceed 30 MB; users re-uploading a podcast or full album rip as BGM; proxy frameworks that buffer the whole body before the size check.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/8e7016eea2efe915. Report an issue: GitHub.