Extract and convert audio using ffmpeg or avconv

pull/72/head
Brandon Skari 2017-05-03 23:30:54 -06:00
rodzic 5d31e1ea07
commit 87cac9d4f6
1 zmienionych plików z 43 dodań i 28 usunięć

Wyświetl plik

@ -1,42 +1,57 @@
"""Hides imports and other irrelevant things so that ipython works nicely."""
from pydub import AudioSegment
import _rpitx
import io
import array
import ffmpegwrapper
import libavwrapper
import logging
import wave
import os
import subprocess
import threading
def broadcast_fm(file_, frequency):
"""Play a music file over FM."""
def broadcast_fm(media_file_name, frequency):
"""Play a media file's audio over FM."""
logging.basicConfig()
logger = logging.getLogger('rpitx')
def _reencode(file_name):
"""Returns an AudioSegment file reencoded to the proper WAV format."""
original = AudioSegment.from_file(file_name)
if original.channels > 2:
raise ValueError('Too many channels in sound file')
if original.channels == 2:
# TODO: Support stereo. For now, just overlay into mono.
logger.info('Reducing stereo channels to mono')
left, right = original.split_to_mono()
original = left.overlay(right)
if subprocess.call(('which', 'ffmpeg')) == 1:
Input = ffmpegwrapper.Input
Output = ffmpegwrapper.Output
VideoCodec = ffmpegwrapper.VideoCodec
AudioCoded = ffmpegwrapper.AudioCodec
Stream = ffmpegwrapper.FFmpeg
command = 'ffmpeg'
elif subprocess.call(('which', 'avconv')) == 1:
Input = libavwrapper.Input
Output = libavwrapper.Output
VideoCodec = libavwrapper.VideoCodec
AudioCoded = libavwrapper.AudioCodec
Stream = libavwrapper.AVConv
command = 'avconv'
else:
raise NotImplementedError(
'Broadcasting audio requires either avconv or ffmpeg to be installed'
)
return original
logger.debug('Using {}'.format(command))
raw_audio_data = _reencode(file_)
pipe_name = '/tmp/rpitx-fifo.wav'
if not os.path.exists(pipe_name):
os.mkfifo(pipe_name)
wav_data = io.BytesIO()
wav_writer = wave.open(wav_data, 'w')
wav_writer.setnchannels(1)
wav_writer.setsampwidth(2)
wav_writer.setframerate(48000)
wav_writer.writeframes(raw_audio_data.raw_data)
wav_writer.close()
def convert():
"""Runs the conversion command and writes to a FIFO."""
input_media = Input(media_file_name)
codec = AudioCodec('pcm_s16le').frequence(48000).channels(1)
output_audio = Output(pipe_name, pipe_out)
stream = Stream(command, input_media, output_audio)
stream.add_option('-y', '') # Force overwriting existing file
logger.debug('Extracting and converting audio')
stream.run()
raw_array = array.array('b', wav_data.getvalue())
array_address, length = raw_array.buffer_info()
_rpitx.broadcast_fm(array_address, length, frequency)
thread = threading.Thread(target=convert)
thread.start()
logger.debug('Calling broadcast_fm')
_rpitx.broadcast_fm(pipe_name, frequency)
thread.join()