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() |