-
-
Save OscarL/8b8d5e60e69b5d16d80bbf62c9e23ab7 to your computer and use it in GitHub Desktop.
CUE splitter using ffmpeg (to mp3)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Changes over the original: | |
# | |
# + Support both Python 2 & 3. | |
# * fixed location of bitrate parameters. | |
# * Fixed track duration so it does't cuts tracks short, nor starts them early | |
# (Margin of error for .flac source files should at most be around +/- 0.013 secs). | |
# + Added pre_gap support. | |
cue_file = 'file.cue' | |
d = open(cue_file).read().splitlines() | |
general = {} | |
tracks = [] | |
current_file = None | |
def index2seconds(line): | |
mm, ss, ff = list(map(int, ' '.join(line.strip().split(' ')[2:]).replace('"', '').split(':'))) | |
return 60 * mm + ss + ff / 75.0 # each FF is 1/75 of a sec | |
def replace_chars(string, chars=r':\/|<>?*"', replacement='_'): | |
""" | |
Return `string` with any char in the `chars` replaced by `replacement`. | |
Defaults to replace problematic/invalid chars for filenames/paths. | |
""" | |
for c in string: | |
if c in chars: | |
string = string.replace(c, replacement) | |
return string | |
for line in d: | |
if line.startswith('REM GENRE '): | |
general['genre'] = ' '.join(line.split(' ')[2:]) | |
if line.startswith('REM DATE '): | |
general['date'] = ' '.join(line.split(' ')[2:]) | |
if line.startswith('PERFORMER '): | |
general['artist'] = ' '.join(line.split(' ')[1:]).replace('"', '') | |
if line.startswith('TITLE '): | |
general['album'] = ' '.join(line.split(' ')[1:]).replace('"', '') | |
if line.startswith('FILE '): | |
current_file = ' '.join(line.split(' ')[1:-1]).replace('"', '') | |
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'] = ' '.join(line.strip().split(' ')[1:]).replace('"', '') | |
if line.startswith(' PERFORMER '): | |
tracks[-1]['artist'] = ' '.join(line.strip().split(' ')[1:]).replace('"', '') | |
if line.startswith(' INDEX 00 '): | |
tracks[-1]['pre_gap'] = index2seconds(line) | |
if line.startswith(' INDEX 01 '): | |
tracks[-1]['start'] = index2seconds(line) | |
for i in range(len(tracks) - 1): | |
if 'pre_gap' in tracks[i + 1]: | |
tracks[i]['duration'] = tracks[i + 1]['pre_gap'] - tracks[i]['start'] | |
else: | |
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 += ' -b:a 320k' | |
cmd += ' -ss %.2d:%.2d:%09.6f' % (track['start'] / 60 / 60, track['start'] / 60 % 60, track['start'] % 60) | |
if 'duration' in track: | |
cmd += ' -t %.2d:%.2d:%09.6f' % (track['duration'] / 60 / 60, track['duration'] / 60 % 60, track['duration'] % 60) | |
cmd += ' ' + ' '.join('-metadata %s="%s"' % (k, v) for (k, v) in metadata.items()) | |
cmd += replace_chars(' "%.2d - %s - %s.mp3"' % (track['track'], track['artist'], track['title'])) | |
print(cmd) |
@maye9999, I just added a basic "replace invalid chars in filenames with _" (Untested), just in case I take too long to move this into a proper git repo.
@OscarL Thank you very much❤
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@maye9999: that seems to be not so much of a problem with ffmpeg, as to with the under-laying filesystem. AFAIK, Macs forbid ":", Linux forbids "/", and Windows forbids a ton of characters and names (<, >, /, . |, ", *, ?) , and ":" is used in NTFS for alternate datastreams.
Workaround: manually replace ":" for " - " in the TITLE lines of your .cue file (or see if the program that created it has an option to do it automatically, most ripping software I used to use had an option like that).
Some more info on stackoverflow.
We should escape such characters to make sure we are using valid filenames, but I feel that it its out of scope for this little gist.
I have a work-in-progress version that actually calls ffmpeg, lets you select the output format, choose if you want metadata or not, things like that... and a bit more error correction. I'll do my best to keep this issue in mind.
I will create a proper git repository for that script, as I want it to have tests, docs, and things like that... all while being a small, easy to follow project for beginners and old timers, like me, that are just a bit rusty :-D
I'll add a comment here when I upload that code.
Thanks again!