Skip to content

Instantly share code, notes, and snippets.

@Vftdan
Forked from Theldus/cue_to_flac.py
Last active August 14, 2022 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Vftdan/54ce7ff8f0a48c643bf7d9681ee2f1e0 to your computer and use it in GitHub Desktop.
Save Vftdan/54ce7ff8f0a48c643bf7d9681ee2f1e0 to your computer and use it in GitHub Desktop.
CUE splitter using ffmpeg (to flac)
#! /usr/bin/env python3
import sys
def unquote(s):
if len(s) < 2:
return s
if s[0] == '"' and s[-1] == '"':
return s[1:-1]
return s
def shellescape(s):
return "'" + s.replace("'", "'\\''") + "'"
d = sys.stdin.read().splitlines()
general = {}
tracks = []
current_file = None
for line in d:
if line.startswith('REM GENRE '):
general['genre'] = unquote(' '.join(line.split(' ')[2:]))
if line.startswith('REM DATE '):
general['date'] = unquote(' '.join(line.split(' ')[2:]))
if line.startswith('PERFORMER '):
general['artist'] = unquote(' '.join(line.split(' ')[1:]))
if line.startswith('TITLE '):
general['album'] = unquote(' '.join(line.split(' ')[1:]))
if line.startswith('FILE '):
current_file = unquote(' '.join(line.split(' ')[1:-1]))
if line.startswith(' '):
line = line.strip() # we want to try our best at handling files with different indentations
if line.startswith('TRACK '):
track = general.copy()
track['track'] = int(line.strip().split(' ')[1], 10)
tracks.append(track)
if line.startswith('TITLE '):
tracks[-1]['title'] = unquote(' '.join(line.strip().split(' ')[1:]))
if line.startswith('PERFORMER '):
tracks[-1]['artist'] = unquote(' '.join(line.strip().split(' ')[1:]))
if line.startswith('INDEX 01 '):
t = tuple(map(int, unquote(' '.join(line.strip().split(' ')[2:])).split(':')))
tracks[-1]['start'] = 60 * t[0] + t[1] + t[2] / 100.0
for i in range(len(tracks)):
if i != len(tracks) - 1:
tracks[i]['duration'] = tracks[i + 1]['start'] - tracks[i]['start']
for track in tracks:
metadata = {
'artist': track['artist'],
'title': track['title'],
'album': track['album'],
'track': str(track['track']) + '/' + str(len(tracks))
}
if 'genre' in track:
metadata['genre'] = track['genre']
if 'date' in track:
metadata['date'] = track['date']
cmd = 'ffmpeg'
cmd += ' -i "%s"' % current_file
cmd += ' -ss ' + shellescape('%.2d:%.2d:%.2d' % (track['start'] / 60 / 60, track['start'] / 60 % 60, int(track['start'] % 60)))
if 'duration' in track:
cmd += ' -t ' + shellescape('%.2d:%.2d:%.2d' % (track['duration'] / 60 / 60, track['duration'] / 60 % 60, int(track['duration'] % 60)))
cmd += ' ' + ' '.join('-metadata ' + shellescape('%s=%s' % (k, v)) for (k, v) in metadata.items())
cmd += ' ' + shellescape('%.2d. %s - %s.flac' % (track['track'], track['artist'], track['title']))
print(cmd)
@Vftdan
Copy link
Author

Vftdan commented Aug 14, 2022

Example invocation for russian windows encoding:

iconv -f CP1251 < file.cue | cue_to_flac_cmd.py | tee to-tracks.sh
sh ./to-tracks.sh

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