Skip to content

Instantly share code, notes, and snippets.

@fxg42
Created October 14, 2017 12:58
Show Gist options
  • Save fxg42/569447c6bee3afefac9f294688ab9543 to your computer and use it in GitHub Desktop.
Save fxg42/569447c6bee3afefac9f294688ab9543 to your computer and use it in GitHub Desktop.
Split a youtube soundtrack into multiple files. Requires youtube-dl, ffmpeg and python3
import sys
import re
import subprocess
import os
#
# Usage:
# $ youtube-dl -f 140 https://www.youtube.com/watch?v=Iq0xfewozjw
# $ python3 split.py <input file name>.m4a tracks.txt
#
#
# Parse track listing. File format:
# nn:nn:nn - track title
#
# Adjust regular expression for different track listings.
#
track_listing = open(sys.argv[2], 'r')
tracks = []
for idx, track_info in enumerate(track_listing):
match = re.search('^([0-9:]+) - (.*)$', track_info)
tracks.append({
'number': str(idx+1).zfill(2),
'title': match.group(2).strip(),
'start_time': match.group(1),
})
track_listing.close()
#
# For each track (except last), calculate end time:
# end_time(track_n) === start_time(track_n+1) - 1 second
#
for idx, track in enumerate(tracks[:-1]):
end_time = tracks[idx+1]['start_time']
components = [int(c) for c in end_time.split(':')]
idx = len(components) - 1
while 0 <= idx:
if components[idx] == 0:
components[idx] = 59
idx -= 1
else:
components[idx] -= 1
break
track['end_time'] = ':'.join([str(c).zfill(2) for c in components])
#
# Issue ffmpeg command for each track
#
current_dir = os.path.dirname(os.path.realpath(__file__))
for track in tracks:
if 'end_time' in track:
subprocess.call([f'ffmpeg -i "{sys.argv[1]}" -acodec copy -ss {track["start_time"]} -to {track["end_time"]} "{track["number"]}-{track["title"]}.m4a"'], shell=True, cwd=current_dir)
else:
subprocess.call([f'ffmpeg -i "{sys.argv[1]}" -acodec copy -ss {track["start_time"]} "{track["number"]}-{track["title"]}.m4a"'], shell=True, cwd=current_dir)
00:00 - Divinity - Original Sin 2 (Main Theme)
03:39 - Mead, Gold, and Blood (Ifan's Theme)
06:19 - Symphony of the Void
09:48 - Rivellon
12:05 - Welcome to Fort Joy
14:08 - A Single Drop of Magic
17:36 - Reflections from the Past
20:18 - Quirky Bones
21:42 - Dancing with the Source
24:07 - Dancing with the Source (Cello Version)
26:31 - Dancing with the Source (Tambura Version)
28:55 - Dancing with the Source (Bansuri Version)
31:21 - Dancing with the Source (Oud Version)
33:46 - Power of Innocence 2017 (Orchestral Version)
37:47 - Reaper's Coast
41:34 - Rivellon (Light Version)
43:51 - A Part of Their Story
48:03 - Amber Ale
51:45 - Driftwood
55:30 - Path of the Godwoken
58:44 - Path of the Godwoken (Tambura Version)
1:01:57 - Path of the Godwoken (Bansuri Version)
1:05:11 - Path of the Godwoken (Oud Version)
1:08:24 - Path of the Godwoken (Cello Version)
1:11:37 - A Tear in the Veil
1:16:15 - Sebille's Theme
1:19:43 - Divine's Lament
1:24:04 - Embrace of the Deathfog
1:28:14 - Fane's Theme
1:30:36 - Sins and Gods (Cello Version)
1:33:15 - Sing for Me (Lohse's Theme)
1:36:10 - Red Prince Theme
1:39:10 - The Queen's High Seas (Beast's Theme)
1:41:44 - Sins and Gods (Strings Version)
1:43:52 - The Battle for Divinity
1:48:55 - Divine's Lament (Bonus Song, lead vocals by Borislav Slavov)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment