Skip to content

Instantly share code, notes, and snippets.

@Ashwinning
Last active July 21, 2023 15:25
Show Gist options
  • Save Ashwinning/a9677b5b3afa426667d979b36c019b04 to your computer and use it in GitHub Desktop.
Save Ashwinning/a9677b5b3afa426667d979b36c019b04 to your computer and use it in GitHub Desktop.
Python Youtube MP3 Splitter #gistblog #python

Python Youtube MP3 Splitter

A Python program that splits mp3 files from YouTube albums into individual songs.

Dependencies

  • Python 2.7+
  • ffmpeg

Getting Started

You need to have Python 2.7+ and ffmpeg installed.

Useful links:

Usage

  1. Install Python and ffmpeg.

  2. Download the album from Youtube as mp3.
    (You could use YouTube-dl or any online service).

youtube-dl --extract-audio --audio-format mp3 --audio-quality 0 <Video-URL>
  1. Download application.py

  2. Copy the timestamps into a .txt file

  3. Run

    python application.py <music file.mp3> <tracklist file.txt>
  4. Enjoy!

import sys
import subprocess
inputfile = sys.argv[1]
codec = '-acodec'
#ffmpeg did not like having '?' in the file name, add any other problematic symbol here.
escape_list = ['?']
def RemoveSymbols(text):
for symbol in escape_list:
text = text.replace(symbol, '')
return text
tracklist = []
class Track:
def __init__(self, timestamp, name):
self.timestamp = timestamp
self.name = name
class ExtractTracks:
def __init__(self):
with open(sys.argv[2], "r") as values:
for value in values:
name = ""
timestamp = ""
#split all by spaces.
keyVal = value.split(' ')
#find timestamp
for word in keyVal:
if ':' in word:
timestamp = word
else:
name += word + ' '
tracklist.append(Track(timestamp, name))
#Initialize
ExtractTracks()
def GenerateSplitCommand(start, end, filename):
return ['ffmpeg', '-i', inputfile, '-ss', start, '-to', end, '-c', 'copy', filename+'.mp3', '-v', 'error']
def GetVideoEnd():
ffprobeCommand = [
'ffprobe',
'-v',
'error',
'-show_entries',
'format=duration',
'-of',
'default=noprint_wrappers=1:nokey=1',
'-sexagesimal',
inputfile
]
return subprocess.check_output(ffprobeCommand).strip()
for i in range(0, len(tracklist)):
name = tracklist[i].name.strip()
name = RemoveSymbols(name)
startTime = tracklist[i].timestamp.strip()
if i != (len(tracklist) - 1):
endTime = tracklist[i+1].timestamp.strip() #- startTime
else:
endTime = GetVideoEnd() #- startTime
print('---')
print('Generating ' + name + ' from ' + startTime + ' to ' + endTime)
print('---')
command = GenerateSplitCommand(str(startTime), str(endTime), name)
output = subprocess.check_call(command)
@octimis
Copy link

octimis commented Jan 20, 2021

Thank you for supplying this script.

I would like to make 2 modifications.

I would like to manually/explicitly specify the 'end time' to the nearest millisecond (as well as start time), e.g.: 00:04:32.549
The reason for this, to get rid of 'extended pauses' to more quickly transition to the next song.
I use a GUI program to visually analyze where the end pause first occurs, and manually write down said time, rather than using my hearing.

The 2nd modification I'd like to do, is use ogg vorbis for output method
I presume for the function def GenerateSplitCommand(start, end, filename), could have it's return statement changed to:
return ['ffmpeg', '-i', inputfile, '-ss', start, '-to', end, '-c' , 'copy', ________________ filename+'.mp3', '-v', 'error']
return ['ffmpeg', '-i', inputfile, '-ss', start, '-to', end, '-c:a', 'libvorbis', 'b:a', '128k', filename+'.ogg', '-v', 'error']

I'm concerned this may be in conflict with the statement, codec = '-acodec'
According to the ffmpeg document, that refers to the Ac-3 decoder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment