kopia lustrzana https://github.com/F5OEO/rpitx
Extract and convert audio using ffmpeg or avconv
rodzic
5d31e1ea07
commit
87cac9d4f6
|
@ -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()
|
||||
|
|
Ładowanie…
Reference in New Issue