def convert_audio(orig_path, tmp_path): print_info("Converting audio (temporary file: '%s')..." % (tmp_path)) arguments = [ "ffmpeg", "-i", orig_path, "-ac", "2", "-ar", "44100", "-y", "-f", "wav", tmp_path ] proc = subprocess.Popen( arguments, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE ) proc.communicate() proc.stdout.close() proc.stdin.close() proc.stderr.close() print_info("Converting audio... done")
def main(): global g_current_increment global g_current_duration global g_current_wait parser = argparse.ArgumentParser( usage=USAGE, description=DESCRIPTION, epilog=EPILOG, formatter_class=argparse.RawDescriptionHelpFormatter ) for param in COMMAND_LINE_PARAMETERS: if param["short"] is None: parser.add_argument( param["long"], help=param["help"], action=param["action"], default=argparse.SUPPRESS ) else: parser.add_argument( param["short"], param["long"], help=param["help"], action=param["action"], default=argparse.SUPPRESS ) arguments = parser.parse_args() # no arguments: show help and exit if len(sys.argv) < 2: parser.print_help() sys.exit(0) # print version and exit if "version" in arguments: print_info("demodocus v%s" % (__version__)) sys.exit(0) # check we have all the required arguments # if not, it will sys.exit() with some error code check_arguments(arguments) # set default values set_default_values(arguments) # check that we have the audio and syncmap files audio_file_path = arguments.audio syncmap_file_path = arguments.syncmap if not os.path.isfile(audio_file_path): print_error("Audio file '%s' does not exist" % (audio_file_path)) sys.exit(1) if not os.path.isfile(syncmap_file_path): print_error("Syncmap file '%s' does not exist" % (syncmap_file_path)) sys.exit(1) # read syncmap syncmap_obj = read_syncmap(syncmap_file_path) if (syncmap_obj is None) or (len(syncmap_obj) == 0): print_error("Syncmap file '%s' could not be read or it has no fragments" % (syncmap_file_path)) sys.exit(1) max_index = len(syncmap_obj) # convert file to .wav tmp_handler, tmp_path = create_temp_file(extension=".wav") convert_audio(audio_file_path, tmp_path) # open wave file wave_obj = wave.open(tmp_path, "rb") sample_width = wave_obj.getsampwidth() channels = wave_obj.getnchannels() frame_rate = wave_obj.getframerate() # raw_input was renamed to input in Python 3.2 input_function = input try: input_function = raw_input except NameError: pass # set global parameters (default or provided by the user) g_current_increment = int(arguments.increment) g_current_duration = float(arguments.duration) g_current_wait = float(arguments.wait) # define pyaudio callback def callback(in_data, frame_count, time_info, status): global g_current_frame_index global g_next_stop_frame_index global g_current_fragment_index global g_current_increment global g_current_duration global g_current_wait if g_current_frame_index >= g_next_stop_frame_index: # we played what we had to play # so we either move to next fragment # or we wait for user input if arguments.continuous: g_current_fragment_index += g_current_increment else: print("Press r, q, x, dVAL, iVAL, +VAL, -VAL, or [1 ... %d]:" % (max_index)) request = input_function() if len(request) == 0: g_current_fragment_index += g_current_increment elif (request == "x") or (request == "q"): # exit g_current_fragment_index = max_index + 1 elif request == "r": # do nothing => will repeat current fragment pass elif request.startswith("d"): try: g_current_duration = float(request[1:]) except: pass elif request.startswith("i"): try: g_current_increment = int(request[1:]) except: pass elif request.startswith("+") or request.startswith("-"): try: g_current_fragment_index += int(request) except: pass else: try: g_current_fragment_index = int(request) except: pass if g_current_fragment_index > max_index: # completed, return return (None, pyaudio.paComplete) fragment = syncmap_obj[g_current_fragment_index - 1] fragment_position = int(frame_rate * float(fragment["begin"])) fragment_duration = int(frame_rate * (float(fragment["end"]) - float(fragment["begin"]))) fragment_duration = min(fragment_duration, int(frame_rate * g_current_duration)) fragment_text = " ".join(fragment["lines"]) print(" [%06d] %s\n" % (g_current_fragment_index, fragment_text)) wave_obj.setpos(fragment_position) g_current_frame_index = fragment_position g_next_stop_frame_index = fragment_position + fragment_duration # read data from the current position and return it data = wave_obj.readframes(frame_count) g_current_frame_index += frame_count return (data, pyaudio.paContinue) # create object pyaudio_obj = pyaudio.PyAudio() stream = pyaudio_obj.open( format=pyaudio_obj.get_format_from_width(sample_width), channels=channels, rate=frame_rate, output=True, stream_callback=callback ) # play stream until it stays active stream.start_stream() while stream.is_active(): time.sleep(0.1) # close the stream stream.stop_stream() stream.close() wave_obj.close() pyaudio_obj.terminate() # remove temp file delete_file(tmp_handler, tmp_path) print_info("Removed file '%s'" % (tmp_path)) # return 0 sys.exit(0)