Shreyas Shankar
Shreyas Shankar

Reputation: 1

How can I convert any random byte string to a playable mp3 file in python3.6?

I have random bytes of data which I need to convert to mp3 format(although it might be noise). And I should be able to play the (noisy) mp3 file.

from pydub import AudioSegment
from pydub.playback import play
import io

data=open("cipher.json","rb").read()
recording = AudioSegment.from_file(io.BytesIO(data), format="mp3")
recording.export('new.mp3', format='mp3') # for export 
play(recording) # for play

Error is as follows:

Traceback (most recent call last):
  File "temp.py", line 17, in <module>
    recording = AudioSegment.from_file(io.BytesIO(data), format="mp3")
  File "/home/shreyas/.local/lib/python3.6/site-packages/pydub/audio_segment.py", line 704, in from_file
    p.returncode, p_err))
pydub.exceptions.CouldntDecodeError: Decoding failed. ffmpeg returned error code: 1

Output from ffmpeg/avlib:

b"ffmpeg version 3.4.4-0ubuntu0.18.04.1 Copyright (c) 2000-2018 the FFmpeg developers\n  built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)\n  configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared\n  libavutil      55. 78.100 / 55. 78.100\n  libavcodec     57.107.100 / 57.107.100\n  libavformat    57. 83.100 / 57. 83.100\n  libavdevice    57. 10.100 / 57. 10.100\n  libavfilter     6.107.100 /  6.107.100\n  libavresample   3.  7.  0 /  3.  7.  0\n  libswscale      4.  8.100 /  4.  8.100\n  libswresample   2.  9.100 /  2.  9.100\n  libpostproc    54.  7.100 / 54.  7.100\n[mp3 @ 0x564e0e6d4fa0] Header missing\n[mp3 @ 0x564e0e6d3900] decoding for stream 0 failed\n[mp3 @ 0x564e0e6d3900] Could not find codec parameters for stream 0 (Audio: mp3, 0 channels, s16p): unspecified frame size\nConsider increasing the value for the 'analyzeduration' and 'probesize' options\nInput #0, mp3, from 'pipe:':\n  Duration: N/A, start: 0.000000, bitrate: N/A\n    Stream #0:0: Audio: mp3, 0 channels, s16p\nStream mapping:\n  Stream #0:0 -> #0:0 (mp3 (native) -> pcm_s16le (native))\n[mp3 @ 0x564e0e6d72e0] Header missing\nError while decoding stream #0:0: Invalid data found when processing input\nFinishing stream 0:0 without any data written to it.\n[abuffer @ 0x564e0e6dba80] Value inf for parameter 'time_base' out of range [0 - 2.14748e+09]\n    Last message repeated 3 times\n[abuffer @ 0x564e0e6dba80] Error setting option time_base to value 1/0.\n[graph_0_in_0_0 @ 0x564e0e6db980] Error applying options to the filter.\nError configuring filter graph\nConversion failed!\n"

Upvotes: 0

Views: 5182

Answers (4)

Momo
Momo

Reputation: 960

This works for me

import base64
from pydub import AudioSegment
import io

base_64_string = "AAAAIGZ0eXBpc29tAAAAAGlzbzhtcDQxZGFzaGNtZmMAAAP7b" # And more ...

def base64_from_string(string : str):
    return base64.b64decode(string)

def export_mp3_from_base64(b : bytes):
    # Do not specify `AudioSegment` `format` property
    audio_segmant = AudioSegment.from_file(io.BytesIO(b))
    # Export the audio file
    audio_segmant.export('new.mp3', format='mp3')

export_mp3_from_base64(base64_from_string(base_64_string))

Upvotes: 0

lys
lys

Reputation: 1027

As others have indicated, the issue here is that you've selected format=mp3 so you're telling ffmpeg (that pydub uses as a dependency) to encode/decode mp3s to process your json file - which it doesn't understand.

From the pydub API Documentation: for AudioSegment(…).from_file()

Supported keyword arguments:

format | Supports "wav" and "raw" natively, requires ffmpeg for all other formats.

"raw" files require 3 additional keyword arguments, sample_width, frame_rate, and channels, denoted below with: raw only. This extra info is required because raw audio files do not have headers to include this info in the file itself like wav files do.

If you are attempting to read non audio files as audio you need to change the format to format=raw However, opening non audio files as raw audio can break your speakers, and/or hurt your ears. I would suggest both removing the DC offset and scaling down the volume as a precaution. Depending on the input data you may get sharp digital noise or nothing at all.

For example, you can try:

from pydub import AudioSegment
from pydub.playback import play
import io

data=open("cipher.json","rb").read()
recording = AudioSegment.from_file(io.BytesIO(data), format="raw", 
                                   frame_rate=44100, channels=2, 
                                   sample_width=2).remove_dc_offset()

# AudioSegments are immutable so we create a new one that is 3.5dB quieter
quieter = recording - 3.5

quieter.export('new.mp3', format='mp3') # for export 
play(quieter) # for play

You will need to experiment with these parameters:

sample_width | Use 1 for 8-bit audio 2 for 16-bit (CD quality) and 4 for 32-bit.

channels | 1 for mono, 2 for stereo.

frame_rate | Also known as sample rate common values are 44100 (44.1kHz - CD audio), and 48000

I would also suggest unpacking the key value pairs from your json file and converting those to bytes (unless there’s something in the json structure you want to try to use) or experimenting with other file types to import. It is likely you will not hear the results you are expecting, experimentation is key.

Upvotes: 0

Naveen Reddy Marthala
Naveen Reddy Marthala

Reputation: 3123

this is how i got audio in byte strings format, recorded in python using 'speech_recognition` package:

import speech_recognition as sr
recognizer = sr.Recognizer()
with mic as source:
    recognizer.adjust_for_ambient_noise(source)
    captured_audio = recognizer.record(source=mic, duration=30)
audio_file = captured_audio.get_wav_data(convert_rate=44100)

this is I converted it to .wav file:
(your audio may be a class and a method of it may have actual bytestring data of your audio, which is the case with me)

import io
audio_in_bytestring = captured_audio.get_wav_data(convert_rate=44100)
recording = AudioSegment.from_file(io.BytesIO(audio_in_bytestring), format="wav")
recording.export("about_speech_recognition.wav", format="wav")

Upvotes: 0

Simona
Simona

Reputation: 379

Try this

from pydub import AudioSegment
from pydub.playback import play
import io

recording = AudioSegment.from_file(io.BytesIO(<put bytes here>), format="mp3")
recording.export('new.mp3', format='mp3') # for export 
play(recording) # for play

Upvotes: 4

Related Questions