This script is intended to take video a YouTube video and audio from another YouTube video and combine them into a new video.
apt install ffmpeg youtube-dl
#!/usr/bin/env python3 | |
""" | |
This takes a youtube video and replaces the audio with an album's audio | |
""" | |
__author__ = "Dana Merrick" | |
__version__ = "0.1.0" | |
__license__ = "MIT" | |
#TODO: use ffmpeg's minterpolate filter to smooth output | |
#TODO: use youtube-dl like this | |
# from __future__ import unicode_literals | |
# import youtube_dl | |
# ydl_opts = {} | |
# with youtube_dl.YoutubeDL(ydl_opts) as ydl: | |
# ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc']) | |
import os | |
import subprocess | |
video_id = "yDiD8F9ItX0" | |
audio_id = "MHf7TimSfrM" | |
def main(): | |
download_files() | |
convert_to_mp4() | |
match_lengths() | |
combine_files() | |
cleanup() | |
def download_files(): | |
video_url = f"https://www.youtube.com/watch?v={video_id}" | |
audio_url = f"https://www.youtube.com/watch?v={audio_id}" | |
cmd = f"youtube-dl -k --id -f bestvideo+bestaudio --merge-output-format mkv {video_url}" | |
print(cmd) | |
os.system(cmd) | |
cmd = f"youtube-dl -k --id --extract-audio --audio-format flac --audio-quality 0 {audio_url}" | |
print(cmd) | |
os.system(cmd) | |
def match_lengths(): | |
video_length = video_frame_count() | |
audio_length = audio_frame_count() | |
multiplier = audio_length / video_length | |
warp_video(multiplier) | |
#TODO: this seems dumb, the only reason I'm doing it is | |
# because video_frame_count only seems to work with mp4 | |
def convert_to_mp4(): | |
# convert it to mp4, remove audio | |
cmd = f"ffmpeg -i {video_id}.mkv -c copy -an {video_id}.mp4" | |
print(cmd) | |
os.system(cmd) | |
# get length of video | |
def video_frame_count(): | |
cmd = f"ffprobe -show_entries stream=duration -of compact -v 0 {video_id}.mp4" | |
print(cmd) | |
result = subprocess.run(cmd.split(" "), stdout=subprocess.PIPE) | |
print(result.stdout) | |
frames = result.stdout.decode("utf-8").split('=')[-1] | |
return float(frames) | |
# get length of audio | |
def audio_frame_count(): | |
cmd = f"ffprobe -show_entries stream=duration -of compact -v 0 {audio_id}.flac" | |
print(cmd) | |
result = subprocess.run(cmd.split(" "), stdout=subprocess.PIPE) | |
print(result.stdout) | |
frames = result.stdout.decode("utf-8").split('=')[-1] | |
return float(frames) | |
def warp_video(multiplier): | |
cmd = f"ffmpeg -i {video_id}.mp4 -filter:v 'setpts={multiplier}*PTS' {video_id}-warped.mp4" | |
print(cmd) | |
os.system(cmd) | |
def combine_files(): | |
cmd = f"ffmpeg -i {video_id}-warped.mp4 -i {audio_id}.flac -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 final-output.mp4" | |
print(cmd) | |
os.system(cmd) | |
def cleanup(): | |
cmd = f"rm {video_id}* {audio_id}*" | |
print(cmd) | |
os.system(cmd) | |
if __name__ == "__main__": | |
main() |