Files
scripts/lecturemunger.py
2021-02-07 23:41:12 +00:00

168 lines
5.9 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests the audacity pipe.
Depends on Destreamer and python-dateutil
Ensure you have a blank Audacity project open before use
Known issues:
- Audio and video slip ever so slightly out of sync
- Audio gets dickered into mono >.>
"""
import shutil
from subprocess import call
import os
import sys
from pathlib import Path
import dateutil.parser as dparser
import re
import time
# TODO
path_to_destreamer = os.path.abspath(sys.argv[1])
working_dir = os.path.abspath(sys.argv[2])
urls = sys.argv[3:]
# Platform specific constants
if sys.platform == 'win32':
print("recording-test.py, running on windows")
PIPE_TO_AUDACITY = '\\\\.\\pipe\\ToSrvPipe'
PIPE_FROM_AUDACITY = '\\\\.\\pipe\\FromSrvPipe'
EOL = '\r\n\0'
else:
print("recording-test.py, running on linux or mac")
PIPE_TO_AUDACITY = '/tmp/audacity_script_pipe.to.' + str(os.getuid())
PIPE_FROM_AUDACITY = '/tmp/audacity_script_pipe.from.' + str(os.getuid())
EOL = '\n'
print("Write to \"" + PIPE_TO_AUDACITY +"\"")
if not os.path.exists(PIPE_TO_AUDACITY):
print(""" ..does not exist.
Ensure Audacity is running with mod-script-pipe.""")
sys.exit()
print("Read from \"" + PIPE_FROM_AUDACITY +"\"")
if not os.path.exists(PIPE_FROM_AUDACITY):
print(""" ..does not exist.
Ensure Audacity is running with mod-script-pipe.""")
sys.exit()
print("-- Both pipes exist. Good.")
TOPIPE = open(PIPE_TO_AUDACITY, 'w')
print("-- File to write to has been opened")
FROMPIPE = open(PIPE_FROM_AUDACITY, 'r')
print("-- File to read from has now been opened too\r\n")
def send_command(command):
"""Send a command to Audacity."""
print("Send: >>> "+command)
TOPIPE.write(command + EOL)
TOPIPE.flush()
def get_response():
"""Get response from Audacity."""
line = FROMPIPE.readline()
result = ""
while True:
result += line
line = FROMPIPE.readline()
# print(f"Line read: [{line}]")
if line == '\n':
return result
def do_command(command):
"""Do the command. Return the response."""
send_command(command)
# time.sleep(0.1) # may be required on slow machines
response = get_response()
print("Rcvd: <<< " + response)
return response
def do_command(command):
"""Send one command, and return the response."""
send_command(command)
response = get_response()
print("Rcvd: <<< \n" + response)
return response
def mkdir_if_not_exists(directory):
if not os.path.exists(directory):
os.makedirs(directory)
return os.path.abspath(directory)
# TODO Cleanup path handling cause...ew
def do():
mkdir_if_not_exists(working_dir)
if working_dir:
print("WARNING: MUNGING IN PROGRESS")
# Setup
#os.chdir(working_dir)
downloaded = mkdir_if_not_exists(working_dir + "/downloaded")
renamed = mkdir_if_not_exists(working_dir + "/renamed")
processed_audio_dir = mkdir_if_not_exists(working_dir + "/processed_audio")
final = mkdir_if_not_exists(working_dir + "/final")
# Download videos
print("Using destreamer.js at {}".format(path_to_destreamer))
call("node --max-http-header-size 32768 {} --skip -k -o {} -i {}".format(path_to_destreamer, downloaded, " ".join(urls)), shell=True)
for entry in os.scandir(downloaded):
# Normalise names
# Put file extension to one side for safekeeping
split = entry.name.split('.')
extension = split[1]
name = split[0].replace(',', '').split('#')[0] # Discard all commas, and unique id doodad
head, sep, tail = name.partition(' ') # Discard leading date
split2 = tail.split()
date = dparser.parse(split2[-1], fuzzy=True) # Parse the date
folder_path = split2[0] + split2[1] # TODO Fragile
title = re.search(r'\d+-\d+\s[\d\w\s]*', tail)
if re.match:
title = title.group(0).strip().replace(' ', '_')
# Add date back
if date is not None:
title += "_" + date.strftime('%Y-%m-%d')
# Rename file
source = entry.path
filename = "{}.{}".format(title, extension)
dest = os.path.abspath(renamed + "/" + filename)
print ("Source: " + source)
print ("Dest: " + dest)
shutil.copy(source, dest)
time.sleep(5)
# Extract audio, process it, add it back to the video
video_in = dest
processed_audio = os.path.join(processed_audio_dir, filename.split(".")[0] + ".wav")
final_output_name = os.path.join(final, filename)
do_command("New:")
do_command("Import2: Filename={}".format(video_in))
time.sleep(5)
do_command("SelectAll:")
do_command('Amplify: Ratio=2')
time.sleep(1)
do_command("SelectAll:")
do_command('Popmute: thresh=10 floor=100')
time.sleep(1)
do_command("Export2: Filename={} NumChannels=2".format(processed_audio))
time.sleep(5)
do_command("SelectAll:")
do_command("RemoveTracks:")
time.sleep(5)
# do_command('Close:') TODO THis causes audacity to wait for a input
# final_output_name = "output-" +
# TODO Folderisation of output by lecture
print("Combining video at {} with audio at {}".format(video_in, processed_audio))
# https://superuser.com/questions/277642/how-to-merge-audio-and-video-file-in-ffmpeg
call('ffmpeg -i {} -i {} -acodec copy -vcodec copy -map 0:v:0 -map 1:a:0 {}'.format(video_in, processed_audio, final_output_name), shell=True)
print("\033[92mDone! Result is at {}\e[0m".format(final_output_name))
print("Munging complete!!!")
do()