audio recording functionality for inter-track fills
parent
2a13dfab7a
commit
ed3c45afda
29
README.md
29
README.md
|
@ -1,14 +1,31 @@
|
|||
# uho
|
||||
# uho!
|
||||
|
||||
usage examples:
|
||||
Some python magick to help making the Uho podcast. https://uho.rizom,si
|
||||
|
||||
./mk_show.py --episode 2 --date 2024-03-11 --playlist keep --web --art --mp3
|
||||
## usage examples:
|
||||
|
||||
./mk_show.py --episode 2 --insert_fill --top_tail
|
||||
### create a new playlist
|
||||
./mk_show.py --episode 2 --date 2024-03-11 --playlist new
|
||||
|
||||
./mk_show.py --episode 2 --date 2024-03-11 --playlist edit --web --art --insert_fill --top_tail
|
||||
### edit an existing playlist
|
||||
./mk_show.py --episode 2 --playlist edit
|
||||
|
||||
when happy with the playlist then record the voice fills:
|
||||
|
||||
### record the voice fills for between the songs
|
||||
each song should have a short intro description and a longer outro description
|
||||
|
||||
### record the intros for track 2
|
||||
./recorder.py -e 2 -f in
|
||||
|
||||
### record the outros for track 2
|
||||
./recorder.py -e 2 -f out
|
||||
|
||||
now you have the voice fills and the playlist - time to cook up the show...
|
||||
|
||||
### keep the playlist and generate a website artwork and an audiofile output
|
||||
./mk_show.py --episode 0 --date 2024-1-30 --playlist keep --mp3 --web --art
|
||||
|
||||
Generative radio show of contemporary Slovenian independent music for Mariborski radio študent - MARŠ. Scripted using Liquidsoap and assorted other scripting glue, bash, python...
|
||||
|
||||
featured labels and artists:
|
||||
https://pharmafabrik.bandcamp.com/
|
||||
|
|
BIN
database/show.db
BIN
database/show.db
Binary file not shown.
|
@ -564,8 +564,8 @@ def create_podcast():
|
|||
if not os.path.exists(archive_path):
|
||||
os.makedirs(archive_path)
|
||||
|
||||
from distutils.dir_util import copy_tree
|
||||
copy_tree("archive/blank_fills/", "archive/e/{0}/audio_fills".format(episode_number))
|
||||
#from distutils.dir_util import copy_tree
|
||||
#copy_tree("archive/blank_fills/", "archive/e/{0}/audio_fills".format(episode_number))
|
||||
|
||||
|
||||
fill_path = "{0}/{1}/audio_fills".format(archive_path, episode_number)
|
||||
|
|
75
recorder.py
75
recorder.py
|
@ -1,22 +1,17 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from pynput import keyboard
|
||||
import time, os
|
||||
import pyaudio
|
||||
import wave
|
||||
import sched
|
||||
import sys
|
||||
#recorder
|
||||
import pyaudio, wave, sched, sys, time, os
|
||||
from playsound import playsound
|
||||
|
||||
from pynput import keyboard
|
||||
from threading import Thread, Lock
|
||||
from pynput import keyboard
|
||||
import pyaudio
|
||||
import wave
|
||||
|
||||
|
||||
import sys, os, datetime, fnmatch, glob, random, time, pathlib, re,\
|
||||
sqlite3, json, subprocess, uuid, argparse, contextlib
|
||||
|
||||
from pydub import AudioSegment
|
||||
|
||||
from datetime import timedelta
|
||||
from os.path import join
|
||||
from tinytag import TinyTag
|
||||
|
@ -29,6 +24,17 @@ from glob import glob
|
|||
import tkinter as tk
|
||||
from tkinter import filedialog as fd
|
||||
|
||||
|
||||
p = pyaudio.PyAudio()
|
||||
info = p.get_host_api_info_by_index(0)
|
||||
numdevices = info.get('deviceCount')
|
||||
|
||||
for i in range(0, numdevices):
|
||||
if (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
|
||||
print("Input Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name'))
|
||||
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-d", "--date", help="Show Date")
|
||||
parser.add_argument("-e", "--episode", help="Episode Number", type=int)
|
||||
|
@ -37,7 +43,7 @@ parser.add_argument("-m", "--mp3", action="store_true")
|
|||
parser.add_argument("-w", "--web", action="store_true")
|
||||
parser.add_argument("-a", "--art", action="store_true")
|
||||
parser.add_argument("-i", "--insert_fills", action="store_true")
|
||||
parser.add_argument("-t", "--top_tail", action="store_true")
|
||||
parser.add_argument("-f", "--fill", help="fill type", type=str)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -51,9 +57,8 @@ episode_author="Rob Canning"
|
|||
|
||||
show_short_description = '''The UhO! podcast presents an eclectic selection of independent music from Slovenia. The show aims to deliver as broad a range of genres as possible; banging techno, sludge, math rock, contemporary classical, doom, free improvisation, noise music, glitch, jazz skronk, field recordings, ambient, drone....etc etc... whatever the genre, you can be sure you are listening to the latest and most inovative music on offer in this part of the world. Hosted and compiled by Rob Canning, the show is published weekly by Zavod Rizoma and is broadcast in Slovenia on FM by mariborski radio študent: MARŠ. It as also available as a podcast. Use our RSS feed or search for UhO Podcast where ever you subscribe to podcasts'''
|
||||
|
||||
|
||||
|
||||
episode_number = args.episode
|
||||
fill = args.fill;
|
||||
input_date = args.date
|
||||
episode_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
episode_duration = 10
|
||||
|
@ -71,7 +76,7 @@ if not os.path.exists(fill_path):
|
|||
|
||||
#TODO lookup metadata from music_db not from episodoe = use uuids!
|
||||
#TODO scrape artist bio from bandcamp?
|
||||
#TODO GET VARIATION PROMPTS
|
||||
#TODO GET VARIATION PROMPT
|
||||
|
||||
def get_playlist_for_fill_recording(conn, episode_number, episode_duration):
|
||||
cursor = conn.cursor()
|
||||
|
@ -80,7 +85,7 @@ def get_playlist_for_fill_recording(conn, episode_number, episode_duration):
|
|||
cursor.execute('SELECT SUM(trackdur) FROM EPISODES WHERE EPISODE=? ', [episode_number])
|
||||
episode_duration = cursor.fetchone()[0]
|
||||
|
||||
os.system("clear")
|
||||
# os.system("clear")
|
||||
print("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
||||
print(">> PROPOSED EPISODE #{0} PLAYLIST: ({1}) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"\
|
||||
.format(episode_number, timedelta(seconds=round(episode_duration))))
|
||||
|
@ -95,7 +100,7 @@ def get_playlist_for_fill_recording(conn, episode_number, episode_duration):
|
|||
|
||||
user_input = input('''
|
||||
(l)isten to track
|
||||
R ECORD OUTRO FILL
|
||||
R ECORD FILL
|
||||
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>> OR PRESS ENTER TO PROCEED................... : ''')
|
||||
|
||||
|
@ -103,13 +108,22 @@ def get_playlist_for_fill_recording(conn, episode_number, episode_duration):
|
|||
playlist_preview_track(conn, episode_number, episode_duration)
|
||||
|
||||
elif user_input == "r":
|
||||
num = input("Which TRACK # to record outro fill for : ")
|
||||
the_file = "archive/e/{0}/audio_fills/{1}_out.wav".format(episode_number, num)
|
||||
|
||||
if fill == "out":
|
||||
num = input("Which TRACK # to record OUTRO fill for : ")
|
||||
the_file = "archive/e/{0}/audio_fills/{1}_out.wav".format(episode_number, num)
|
||||
elif fill == "in":
|
||||
num = input("Which TRACK # to record INTRO fill for : ")
|
||||
the_file = "archive/e/{0}/audio_fills/{1}_in.wav".format(episode_number, num)
|
||||
else:
|
||||
print("must speficy in or out")
|
||||
|
||||
|
||||
print(the_file)
|
||||
r = recorder(the_file)
|
||||
p = player(the_file)
|
||||
l = listener(r, p)
|
||||
os.system("clear")
|
||||
#os.system("clear")
|
||||
|
||||
for i in preview[int(num)-1:int(num)]:
|
||||
print('''
|
||||
|
@ -157,12 +171,15 @@ class player:
|
|||
|
||||
#contents of the run function are processed in another thread so we use the blocking
|
||||
# version of pyaudio play file example: http://people.csail.mit.edu/hubert/pyaudio/#play-wave-example
|
||||
|
||||
def run(self):
|
||||
with self.lock:
|
||||
self.playing += 1
|
||||
with wave.open(self.wavfile, 'rb') as wf:
|
||||
p = pyaudio.PyAudio()
|
||||
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
|
||||
input_device_index=4,
|
||||
output_device_index=4,
|
||||
channels=wf.getnchannels(),
|
||||
rate=wf.getframerate(),
|
||||
output=True)
|
||||
|
@ -195,7 +212,7 @@ class recorder:
|
|||
self.channels = channels
|
||||
self.rate = rate
|
||||
self.recording = False
|
||||
self.pa = pyaudio.PyAudio()
|
||||
self.p = pyaudio.PyAudio()
|
||||
|
||||
def start(self):
|
||||
#we call start and stop from the keyboard listener, so we use the asynchronous
|
||||
|
@ -204,7 +221,7 @@ class recorder:
|
|||
if not self.recording:
|
||||
self.wf = wave.open(self.filename, 'wb')
|
||||
self.wf.setnchannels(self.channels)
|
||||
self.wf.setsampwidth(self.pa.get_sample_size(self.dataformat))
|
||||
self.wf.setsampwidth(self.p.get_sample_size(self.dataformat))
|
||||
self.wf.setframerate(self.rate)
|
||||
|
||||
def callback(in_data, frame_count, time_info, status):
|
||||
|
@ -212,14 +229,16 @@ class recorder:
|
|||
self.wf.writeframes(in_data)
|
||||
return (in_data, pyaudio.paContinue)
|
||||
|
||||
self.stream = self.pa.open(format = self.dataformat,
|
||||
channels = self.channels,
|
||||
rate = self.rate,
|
||||
input = True,
|
||||
stream_callback = callback)
|
||||
self.stream = self.p.open(format = self.dataformat,
|
||||
input_device_index=4,
|
||||
output_device_index=4,
|
||||
channels = self.channels,
|
||||
rate = self.rate,
|
||||
input = True,
|
||||
stream_callback = callback)
|
||||
self.stream.start_stream()
|
||||
self.recording = True
|
||||
print('recording started')
|
||||
print('recording started',end='')
|
||||
|
||||
def stop(self):
|
||||
if self.recording:
|
||||
|
@ -228,7 +247,7 @@ class recorder:
|
|||
self.wf.close()
|
||||
|
||||
self.recording = False
|
||||
print('recording finished')
|
||||
print('recording finished',end='')
|
||||
|
||||
class listener(keyboard.Listener):
|
||||
|
||||
|
|
Loading…
Reference in New Issue