jiaaro / pydub

Manipulate audio with a simple and easy high level interface
http://pydub.com
MIT License
8.97k stars 1.05k forks source link

pydub always uses pipes with ffmpeg, but ffmpeg can't process some files via pipes #415

Open novocaine opened 5 years ago

novocaine commented 5 years ago

Steps to reproduce

Attempt to open the attached file using pydub.

import pydub
f = open("2036ffa83b6905796a9046ac8b22137135d9fe38_875ac0e8-08ff-4713-8289-6e12dd1cdd95.mp3", "rb")
pydub.AudioSegment.from_file(f, "mp4")

----

Traceback (most recent call last):
  File "test_pydub.py", line 3, in <module>
    pydub.AudioSegment.from_file(f, "mp4")
  File "/usr/local/lib/python3.7/site-packages/pydub/audio_segment.py", line 708, in from_file
    obj = cls._from_safe_wav(BytesIO(p_out))
  File "/usr/local/lib/python3.7/site-packages/pydub/audio_segment.py", line 739, in _from_safe_wav
    obj = cls(data=file)
  File "/usr/local/lib/python3.7/site-packages/pydub/audio_segment.py", line 218, in __init__
    wav_data = read_wav_audio(data)
  File "/usr/local/lib/python3.7/site-packages/pydub/audio_segment.py", line 128, in read_wav_audio
    raise CouldntDecodeError("Couldn't find data header in wav data")
pydub.exceptions.CouldntDecodeError: Couldn't find data header in wav data

This is because the underlying ffmpeg call fails if you process this file via a pipe:

cat 2036ffa83b6905796a9046ac8b22137135d9fe38_875ac0e8-08ff-4713-8289-6e12dd1cdd95.mp3 | ffmpeg -y -f mp4 -i - -acodec pcm_s16le -vn -f wav output.wav

ffmpeg version 4.1.3-1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-7)
  configuration: --prefix=/usr --extra-version=1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x564c7b2537c0] stream 0, offset 0x20: partial file
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2019-08-27T09:10:02.000000Z
    com.android.version: 9
  Duration: 00:00:02.83, bitrate: N/A
    Stream #0:0(eng): Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
    Metadata:
      creation_time   : 2019-08-27T09:10:02.000000Z
      handler_name    : SoundHandle
Stream mapping:
  Stream #0:0 -> #0:0 (aac (native) -> pcm_s16le (native))
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x564c7b2537c0] stream 0, offset 0x20: partial file
pipe:: Invalid data found when processing input
Output #0, wav, to 'output.wav':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    com.android.version: 9
    ISFT            : Lavf58.20.100
    Stream #0:0(eng): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s (default)
    Metadata:
      creation_time   : 2019-08-27T09:10:02.000000Z
      handler_name    : SoundHandle
      encoder         : Lavc58.35.100 pcm_s16le
size=       0kB time=00:00:00.00 bitrate=N/A speed=   0x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)

however if you pass it as a file, its fine

ffmpeg -y -f mp4 -i 2036ffa83b6905796a9046ac8b22137135d9fe38_875ac0e8-08ff-4713-8289-6e12dd1cdd95.mp3 -acodec pcm_s16le -vn -f wav output.wav

ffmpeg version 4.1.3-1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-7)
  configuration: --prefix=/usr --extra-version=1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2036ffa83b6905796a9046ac8b22137135d9fe38_875ac0e8-08ff-4713-8289-6e12dd1cdd95.mp3':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2019-08-27T09:10:02.000000Z
    com.android.version: 9
  Duration: 00:00:02.83, start: 0.000000, bitrate: 99 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
    Metadata:
      creation_time   : 2019-08-27T09:10:02.000000Z
      handler_name    : SoundHandle
Stream mapping:
  Stream #0:0 -> #0:0 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, wav, to 'output.wav':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    com.android.version: 9
    ISFT            : Lavf58.20.100
    Stream #0:0(eng): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s (default)
    Metadata:
      creation_time   : 2019-08-27T09:10:02.000000Z
      handler_name    : SoundHandle
      encoder         : Lavc58.35.100 pcm_s16le
size=     244kB time=00:00:02.83 bitrate= 705.8kbits/s speed= 113x
video:0kB audio:244kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.031218%

I think this is because ffmpeg simply doesn't work for all files using piped input, e.g. see this https://lists.ffmpeg.org/pipermail/ffmpeg-user/2012-November/011084.html

Expected behavior

pydub processes my attached file

Actual behavior

pydub can't process the attached file

Your System configuration

Is there an audio file you can include to help us reproduce?

2036ffa83b6905796a9046ac8b22137135d9fe38_875ac0e8-08ff-4713-8289-6e12dd1cdd95.mp3.zip

novocaine commented 5 years ago

I have worked around this using AudioSegment.from_file_using_temporary_files, but I'm not sure if I'm supposed to be relying on that?

thfalan commented 5 years ago

Been encountering the same issue and your work-around saved me....thanks but what is the difference between "from_file" vs "from_file_using_temporary_files"?

novocaine commented 5 years ago

if you look at the code, from_file_using_temporary_files is an undocumented method that passes the file to ffmpeg using a temporary file, rather than passing it via stdin