13 Commits
3 changed files with 87 additions and 40 deletions
+13 -12
View File
@@ -1,22 +1,22 @@
# flac2pod # flac2pod
Seamlessly converts your existing FLAC library to be played on an iPod Classic. Converts your existing FLAC library to be played on an iPod Classic.
This script makes use of ffmpeg to convert your existing FLAC music library to MP3-320 for easy iPod Classic use. It also takes advantage of "rg2sc" (https://github.com/rwinkhart/rg2sc) to convert any existing ReplayGain tags to Apple Sound Check tags that are compatible with Apple products. This script makes use of ffmpeg to convert your existing FLAC music library to AAC-256 or MP3-320 for easy iPod Classic use. It also takes advantage of "rg2sc" (https://github.com/rwinkhart/rg2sc) to convert any existing ReplayGain tags to Apple SoundCheck tags that are compatible with Apple products.
# Usage # Usage
Simply run: Simply run...
``` ```
flac2pod flac2pod <source_dir> <destination_dir>
``` ```
...and you will be prompted for your source and destination directories. ...to convert your library, or run...
```
flac2pod --help
```
...to see additional options.
In order for flac2pod to function, your source_dir must be structured as follows:
In order for flac2pod to function, your library must be structured as follows: source_dir -> artist dir -> album dir -> FLAC files
library parent dir -> artist dir -> album dir -> FLAC files
When prompted for the source directory, you want to input your library parent directory.
# Installation # Installation
@@ -24,4 +24,5 @@ flac2pod is available in the AUR as "flac2pod". If installing on a non-Arch-base
- copy the flac2pod executable from https://github.com/rwinkhart/flac2pod/blob/master/bin/flac2pod to your /usr/bin/ - copy the flac2pod executable from https://github.com/rwinkhart/flac2pod/blob/master/bin/flac2pod to your /usr/bin/
- copy the rg2sc executable from https://github.com/rwinkhart/rg2sc/blob/master/bin/rg2sc to your /usr/bin - copy the rg2sc executable from https://github.com/rwinkhart/rg2sc/blob/master/bin/rg2sc to your /usr/bin
- install python-mutagen, ffmpeg, and lame - install python-mutagen, ffmpeg, lame, and screen
- start converting
Regular → Executable
+73 -27
View File
@@ -2,11 +2,13 @@
# external modules # external modules
from argparse import ArgumentParser
from mutagen.flac import FLAC
from os import cpu_count, path, walk from os import cpu_count, path, walk
from pathlib import Path from pathlib import Path
from sys import argv, exit as s_exit
from time import sleep
from subprocess import check_output, Popen from subprocess import check_output, Popen
from sys import exit as s_exit
from time import sleep
# utility functions # utility functions
@@ -37,15 +39,23 @@ def create_destination():
.mkdir(0o700, parents=True, exist_ok=True) .mkdir(0o700, parents=True, exist_ok=True)
def scan_destination_convert_mp3(): def scan_destination_convert():
_i, _total_files = 0, len(source_directories) _i, _i_total, _total_files = 0, 0, len(source_directories[1])
for _file in source_directories[1]: for _file in source_directories[1]:
if not Path(f"{_file.replace(path.expanduser(source), path.expanduser(destination))}.mp3").is_file(): _i_total += 1
_file_s = _file.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace\ _progress = round((_i_total / _total_files) * 100, 2)
('&', '\\&').replace('`', '\\`').replace('$', '\\$') + '.flac' if not Path(f"{_file.replace(path.expanduser(source), path.expanduser(destination))}.mp3").is_file() and not \
_file_d = _file.replace(path.expanduser(source), path.expanduser(destination)).replace(' ', '\\ ')\ Path(f"{_file.replace(path.expanduser(source), path.expanduser(destination))}.m4a").is_file():
.replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace('&', '\\&')\ _file_s = _file.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)').replace('(', '\\(')\
.replace('`', '\\`').replace('$', '\\$') + '.mp3' .replace('&', '\\&').replace('`', '\\`').replace('$', '\\$') + '.flac'
if args.mp3:
_file_d = _file.replace(path.expanduser(source), path.expanduser(destination)).replace(' ', '\\ ') \
.replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace('&', '\\&') \
.replace('`', '\\`').replace('$', '\\$') + '.mp3'
else:
_file_d = _file.replace(path.expanduser(source), path.expanduser(destination)).replace(' ', '\\ ') \
.replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace('&', '\\&') \
.replace('`', '\\`').replace('$', '\\$') + '.m4a'
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1 _active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
if _active_processes >= cpu_count(): if _active_processes >= cpu_count():
while _active_processes >= cpu_count(): while _active_processes >= cpu_count():
@@ -53,14 +63,36 @@ def scan_destination_convert_mp3():
sleep(1) sleep(1)
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1 _active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
_i += 1 _i += 1
_progress = _i / _total_files
print(f"\n{_progress}% | \u001b[38;5;0;48;5;15mConverting {_file_s} to {_file_d}...\u001b[0m\n") print(f"\n{_progress}% | \u001b[38;5;0;48;5;15mConverting {_file_s} to {_file_d}...\u001b[0m\n")
if '-s' in arguments: if args.mp3:
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -map 0:a -ab 320k -map_metadata 0" \ if args.strip:
f" -id3v2_version 3 {_file_d} </dev/null; rg2sc -f -s {_file_d}" _cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -map 0:a -ab 320k -map_metadata 0" \
f" -id3v2_version 3 {_file_d} </dev/null; rg2sc -f -s {_file_d}"
else:
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:v copy -ab 320k -map_metadata 0" \
f" -id3v2_version 3 {_file_d} </dev/null; rg2sc -f {_file_d}"
else: else:
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:v copy -ab 320k -map_metadata 0" \ _audio = FLAC(f"{_file}.flac")
f" -id3v2_version 3 {_file_d} </dev/null; rg2sc -f {_file_d}" if _audio.get('replaygain_track_gain'):
_rggain = float(_audio.get('replaygain_track_gain')[0][:-3])
elif _audio.get('REPLAYGAIN_TRACK_GAIN'):
_rggain = float(_audio.get('REPLAYGAIN_TRACK_GAIN')[0][:-3])
else:
_rggain = None
if _audio.get('replaygain_track_peak'):
_rgpeak = float(_audio.get('replaygain_track_peak')[0])
elif _audio.get('REPLAYGAIN_TRACK_PEAK'):
_rgpeak = float(_audio.get('REPLAYGAIN_TRACK_PEAK')[0])
else:
_rgpeak = None
if args.strip:
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:a aac -ab 256k -map_metadata 0 -metadata" \
f" comment='FLAC2PODRG#{_rggain}#{_rgpeak}#' -aac_pns 0 -movflags +faststart -vn" \
f" {_file_d} </dev/null; rg2sc -f -s {_file_d}"
else:
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:a aac -ab 256k -c:v copy -map_metadata" \
f" 0 -metadata comment='FLAC2PODRG#{_rggain}#{_rgpeak}#' -aac_pns 0 -movflags +faststart" \
f" {_file_d} </dev/null; rg2sc -f {_file_d}"
Popen(_cmd, shell=True) Popen(_cmd, shell=True)
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1 _active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
while _active_processes != 0: while _active_processes != 0:
@@ -72,16 +104,30 @@ def scan_destination_convert_mp3():
s_exit() s_exit()
# retrieve typed argument # argument parsing
arguments = argv if __name__ == "__main__":
parser = ArgumentParser(description='Convert your existing FLAC library to be played on an iPod Classic.')
parser.add_argument('source_dir', nargs='+',
help='directory tree containing music files - folder must contain library sorted into artists '
'and albums')
parser.add_argument('destination_dir', nargs='+',
help='destination parent directory for output - will be created if it does not already exist')
parser.add_argument('-s', '--strip', action='store_true',
help='strip all TXXX, APIC, and covr tags from the output files')
parser.add_argument('--mp3', action='store_true',
help='convert to MP3, as opposed to the default of AAC .M4A')
source = input('Source parent directory: ') args = parser.parse_args()
if source.endswith('/'):
source = source[:-1]
destination = input('Destination parent directory: ')
if destination.endswith('/'):
destination = destination[:-1]
source_directories = scan_source() if args.source_dir[0].endswith('/'):
create_destination() source = args.source_dir[0][:-1]
scan_destination_convert_mp3() else:
source = args.source_dir[0]
if args.destination_dir[0].endswith('/'):
destination = args.destination_dir[0][:-1]
else:
destination = args.destination_dir[0]
source_directories = scan_source()
create_destination()
scan_destination_convert()
+1 -1
View File
@@ -39,7 +39,7 @@ pkgdesc='Converts your FLAC library to be iPod-ready'
url='https://github.com/rwinkhart/flac2pod' url='https://github.com/rwinkhart/flac2pod'
arch=('any') arch=('any')
license=('GPL2') license=('GPL2')
depends=(python ffmpeg lame rg2sc) depends=(python ffmpeg lame rg2sc screen python-mutagen)
source=(\""$source"\") source=(\""$source"\")
sha512sums=('"$sha512"') sha512sums=('"$sha512"')