mirror of
https://github.com/rwinkhart/flac2pod.git
synced 2026-09-01 22:57:18 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5a2b9adb3 | ||
|
|
3c7ec3e921 | ||
|
|
10973e3ac8 | ||
|
|
c8ef53bc17 | ||
|
|
144c3f53e0 | ||
|
|
998c73c20f | ||
|
|
df1dce38eb | ||
|
|
ed12cc5d23 | ||
|
|
f72d3ac9b7 | ||
|
|
95a8dacd29 | ||
|
|
d64f4c56fa | ||
|
|
137e30c80b | ||
|
|
be5c96e182 | ||
|
|
7db318b561 | ||
|
|
dee1c3158f | ||
|
|
d973a3f659 | ||
|
|
d00e516e6c | ||
|
|
ea485480c4 | ||
|
|
b56dd7e5f5 |
@@ -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
|
||||||
|
|||||||
+92
-22
@@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
# external modules
|
# external modules
|
||||||
|
|
||||||
from os import path, system, walk
|
from argparse import ArgumentParser
|
||||||
|
from mutagen.flac import FLAC
|
||||||
|
from os import cpu_count, path, walk
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from subprocess import check_output, Popen
|
||||||
|
from sys import exit as s_exit
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
|
||||||
# utility functions
|
# utility functions
|
||||||
@@ -34,30 +39,95 @@ 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, _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("'", "\\'") + '.flac'
|
_progress = round((_i_total / _total_files) * 100, 2)
|
||||||
_file_d = _file.replace(path.expanduser(source),
|
if not Path(f"{_file.replace(path.expanduser(source), path.expanduser(destination))}.mp3").is_file() and not \
|
||||||
path.expanduser(destination)).replace(' ', '\\ ').replace("'", "\\'") + '.mp3'
|
Path(f"{_file.replace(path.expanduser(source), path.expanduser(destination))}.m4a").is_file():
|
||||||
print(f"\n\u001b[38;5;0;48;5;15mConverting {_file_s} to {_file_d}...\u001b[0m\n")
|
_file_s = _file.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)').replace('(', '\\(')\
|
||||||
system(f"ffmpeg -i {_file_s} -c:v copy -ab 320k -map_metadata 0 -id3v2_version 3 {_file_d}")
|
.replace('&', '\\&').replace('`', '\\`').replace('$', '\\$') + '.flac'
|
||||||
rg2sc(_file_d)
|
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
|
||||||
|
if _active_processes >= cpu_count():
|
||||||
|
while _active_processes >= cpu_count():
|
||||||
|
print(f"\nThere are already {cpu_count()} processes running...\n")
|
||||||
|
sleep(1)
|
||||||
|
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
|
||||||
|
_i += 1
|
||||||
|
print(f"\n{_progress}% | \u001b[38;5;0;48;5;15mConverting {_file_s} to {_file_d}...\u001b[0m\n")
|
||||||
|
if args.mp3:
|
||||||
|
if args.strip:
|
||||||
|
_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:
|
||||||
|
_audio = FLAC(f"{_file}.flac")
|
||||||
|
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)
|
||||||
|
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
|
||||||
|
while _active_processes != 0:
|
||||||
|
print('\nPlease wait for the remaining conversions to complete...\n')
|
||||||
|
sleep(1)
|
||||||
|
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
|
||||||
|
sleep(1)
|
||||||
|
print('\niPod conversion complete!\n')
|
||||||
|
s_exit()
|
||||||
|
|
||||||
|
|
||||||
def rg2sc(_file):
|
# argument parsing
|
||||||
system(f"rg2sc -f {_file}")
|
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')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
# program start sequence
|
if args.source_dir[0].endswith('/'):
|
||||||
|
source = args.source_dir[0][:-1]
|
||||||
|
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 = input('Source parent directory: ')
|
source_directories = scan_source()
|
||||||
if source.endswith('/'):
|
create_destination()
|
||||||
source = source[:-1]
|
scan_destination_convert()
|
||||||
destination = input('Destination parent directory: ')
|
|
||||||
if destination.endswith('/'):
|
|
||||||
destination = destination[:-1]
|
|
||||||
|
|
||||||
source_directories = scan_source()
|
|
||||||
create_destination()
|
|
||||||
scan_destination_convert_mp3()
|
|
||||||
|
|||||||
+1
-1
@@ -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"')
|
||||||
|
|||||||
Reference in New Issue
Block a user