def probe_format(cls, filename: str) -> AudioFormatInfo: # first try to use miniaudio if it's available if miniaudio: try: info = miniaudio.get_file_info(filename) except miniaudio.DecodeError: pass # not a file recognised by miniaudio else: sample_format = { miniaudio.SampleFormat.UNKNOWN: "?", miniaudio.SampleFormat.UNSIGNED8: "8", miniaudio.SampleFormat.SIGNED16: "16", miniaudio.SampleFormat.SIGNED24: "24", miniaudio.SampleFormat.SIGNED32: "32", miniaudio.SampleFormat.FLOAT32: "float" }[info.sample_format] return AudioFormatInfo(info.sample_rate, info.nchannels, sample_format, info.sample_width * 8, info.file_format, info.duration, info.num_frames) # if it's a .wav, we can open that ourselves try: with wave.open(filename, "rb") as wf: duration = wf.getnframes() / wf.getframerate() return AudioFormatInfo(wf.getframerate(), wf.getnchannels(), str(wf.getsampwidth() * 8), wf.getsampwidth() * 8, "wav", duration, wf.getnframes()) except wave.Error: pass # fall back to the probe tool command = [ cls.ffprobe_executable, "-v", "error", "-print_format", "json", "-show_format", "-show_streams", "-i", filename ] probe = subprocess.check_output(command) probe = json.loads(probe.decode()) stream = [ stream for stream in probe["streams"] if stream["codec_type"] == "audio" ][0] if not stream: raise IOError("file contains no audio stream, not supported") samplerate = int(stream["sample_rate"]) nchannels = int(stream["channels"]) sampleformat = { "u8": "8", "u8p": "8", "s16": "16", "s16p": "16", "s32": "32", "s32p": "32", "fltp": "float", "flt": "float", }.get(stream["sample_fmt"], "<unknown>") bitspersample = stream["bits_per_sample"] if bitspersample == 0: if sampleformat == "float": bitspersample = 32 else: try: bitspersample = int(sampleformat) except ValueError: pass fileformat = stream["codec_name"] duration = stream.get("duration") or probe["format"].get("duration") duration = float(duration) if duration else 0.0 num_frames = 0 if duration > 0: num_frames = samplerate / duration result = AudioFormatInfo(samplerate, nchannels, sampleformat, bitspersample, fileformat, duration, num_frames) log.debug("format probe of %s: %s", filename, result) return result
def _get_duration(row): id, path = row return id, miniaudio.get_file_info(path).duration
def show_info(filename): info = miniaudio.get_file_info(filename) print("file:", info.name) print("format:", info.file_format) print("{} channels, {} khz, {:.1f} seconds".format(info.nchannels, info.sample_rate, info.duration)) print("{} bytes per sample: {}".format(info.sample_width, info.sample_format_name))
""" Convert an audio file to WAV and different sample formats. """ import os import array import miniaudio def samples_path(filename): return os.path.join(os.path.abspath(os.path.dirname(__file__)), 'samples', filename) src = miniaudio.decode_file(samples_path("music.ogg"), dither=miniaudio.DitherMode.TRIANGLE) print("Source: ", src) result = miniaudio.DecodedSoundFile("result", 1, 22050, miniaudio.SampleFormat.UNSIGNED8, array.array('b')) converted_frames = miniaudio.convert_frames(src.sample_format, src.nchannels, src.sample_rate, src.samples.tobytes(), result.sample_format, result.nchannels, result.sample_rate) # note: currently it is not possible to provide a dithermode to convert_frames() result.num_frames = int(len(converted_frames) / result.nchannels / result.sample_width) result.samples.frombytes(converted_frames) miniaudio.wav_write_file("converted.wav", result) print("Converted sound written to ./converted.wav") output_info = miniaudio.get_file_info("converted.wav") print(output_info)
chunk = buffer[:chunksize] buffer = buffer[chunksize:] chunksize = (yield chunk) * num_channels def stream_file(info, filename): if info.file_format == miniaudio.FileFormat.FLAC: fstream = miniaudio.flac_stream_file(filename) elif info.file_format == miniaudio.FileFormat.MP3: fstream = miniaudio.mp3_stream_file(filename) elif info.file_format == miniaudio.FileFormat.VORBIS: fstream = miniaudio.vorbis_stream_file(filename) elif info.file_format == miniaudio.FileFormat.WAV: fstream = miniaudio.wav_stream_file(filename) else: raise IOError("unsupported audio file format") stream = playback_stream(fstream, info.nchannels) next(stream) # start the generator with miniaudio.PlaybackDevice(output_format=info.sample_format, sample_rate=info.sample_rate, nchannels=info.nchannels) as play: play.start(stream) input("Audio file playing in the background. Enter to stop playback: ") if __name__ == "__main__": if len(sys.argv) != 2: raise SystemExit("use one argument: filename") info = miniaudio.get_file_info(sys.argv[1]) print(info) stream_file(info, sys.argv[1])