5 Commits
5 changed files with 76 additions and 84 deletions
+2 -4
View File
@@ -26,8 +26,6 @@ source_dir -> artist dir -> album dir -> FLAC files
# Installation # Installation
flac2pod is available in the AUR as "flac2pod". If installing on a non-Arch-based distribution, follow the manual installation instructions: flac2pod is available in the AUR as "flac2pod".
- copy the contents of https://github.com/rwinkhart/flac2pod/blob/master/bin/ to your /usr/bin/ If installing on a non-Arch-based distribution, a generic package is available on the releases page.
- install flac, python-mutagen, ffmpeg, and screen
- start converting
-1
View File
@@ -1 +0,0 @@
/usr/bin/flac2pod
@@ -1,10 +1,10 @@
#!/bin/python3 #!/usr/bin/env python3
from argparse import ArgumentParser from argparse import ArgumentParser
from flac2pod import scan_source from flac2pod import scan_source
from mutagen.flac import FLAC, FLACNoHeaderError from mutagen.flac import FLAC, FLACNoHeaderError
from os import listdir, system from os import listdir, system
from subprocess import PIPE, Popen, STDOUT from subprocess import PIPE, run
from sys import exit as s_exit from sys import exit as s_exit
# argument parsing # argument parsing
@@ -42,26 +42,24 @@ if __name__ == "__main__":
if gain != 2 and (args.force or gain == 0): if gain != 2 and (args.force or gain == 0):
print(f"[{album}/*] Adding ReplayGain data...") print(f"[{album}/*] Adding ReplayGain data...")
system(f"metaflac --remove-replay-gain {std_album}/*") system(f"metaflac --remove-replay-gain {std_album}/*")
command = f"metaflac --add-replay-gain {std_album}/*" output = run(f"metaflac --add-replay-gain {std_album}/*", shell=True, stderr=PIPE, text=True)
output = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
block = output.communicate()[0].strip() # blocks the program from proceeding until stdout is given
if output.returncode == 1: if output.returncode == 1:
if block.decode('utf-8').__contains__('sample') or block.decode('utf-8').__contains__('resolution of'): if output.stderr.__contains__('sample') or output.stderr.__contains__('resolution of') or output.\
print('Resolution/Sample Rate mismatch, scanning tracks as individuals...') stderr.__contains__('does not match'):
print('Resolution/Sample Rate/Channel mismatch, scanning tracks as individuals...')
for song in listdir(album): for song in listdir(album):
print(f"[{album}/{song}] Adding ReplayGain data...") print(f"[{album}/{song}] Adding ReplayGain data...")
std_song = song.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)')\ std_song = song.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)')\
.replace('(', '\\(').replace('&', '\\&').replace('`', '\\`').replace('$', '\\$') .replace('(', '\\(').replace('&', '\\&').replace('`', '\\`').replace('$', '\\$')
command = f"metaflac --add-replay-gain {std_album}/{std_song}" output = run(f"metaflac --add-replay-gain {std_album}/{std_song}", shell=True, stderr=PIPE,
output = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) text=True)
block = output.communicate()[0].strip()
if output.returncode == 1: if output.returncode == 1:
print('There was an error processing your files.') print('There was an error processing your files.')
print(f"Return Code: [{str(output.returncode)}] {block.decode('utf-8')}") print(f"Return Code: [{str(output.returncode)}] {output.stderr}")
s_exit(1) s_exit(1)
else: else:
print('There was an error processing your files.') print('There was an error processing your files.')
print(f"Return Code: [{str(output.returncode)}] {block.decode('utf-8')}") print(f"Return Code: [{str(output.returncode)}] {output.stderr}")
s_exit(1) s_exit(1)
else: else:
+43 -41
View File
@@ -1,9 +1,9 @@
#!/bin/python3 #!/usr/bin/env python3
# external modules # external modules
from argparse import ArgumentParser from argparse import ArgumentParser
from mutagen.flac import FLAC, FLACNoHeaderError 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 shutil import copy from shutil import copy
@@ -29,7 +29,8 @@ def scan_source(_source):
for _album in sorted(_album_dirs): for _album in sorted(_album_dirs):
for _root, _directories, _files in walk(path.expanduser(_album)): for _root, _directories, _files in walk(path.expanduser(_album)):
for _filename in _files: for _filename in _files:
if _filename.endswith('.flac'): if _filename.endswith('.flac') or _filename.endswith('.mp3') or _filename.endswith('.mp4') \
or _filename.endswith('.m4a'):
_full_paths.append(f"{_album}/{_filename}") _full_paths.append(f"{_album}/{_filename}")
return _album_dirs, _full_paths return _album_dirs, _full_paths
@@ -45,23 +46,28 @@ def scan_destination_convert():
for _file in source_directories[1]: for _file in source_directories[1]:
_i_total += 1 _i_total += 1
_progress = round((_i_total / _total_files) * 100, 2) _progress = round((_i_total / _total_files) * 100, 2)
if not Path(f"{(_file.replace(path.expanduser(source), path.expanduser(destination)))[:-5]}.m4a").is_file(): if not Path(f"{(_file.replace(path.expanduser(source), path.expanduser(destination)))[:-5]}.m4a").is_file()\
_file_s = _file.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)').replace('(', '\\(')\ and not Path(f"{(_file.replace(path.expanduser(source), path.expanduser(destination)))}").is_file():
.replace(']', '\\]').replace('[', '\\[').replace('&', '\\&').replace('`', '\\`')\ if not _file.endswith('.flac'):
.replace('$', '\\$') print(f"[{_file}] Not a FLAC file, copying...")
_file_d = _file.replace(path.expanduser(source), path.expanduser(destination)).replace(' ', '\\ ')\ copy(f"{_file}", f"{_file.replace(path.expanduser(source), path.expanduser(destination))}")
.replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace(']', '\\]')\ else:
.replace('[', '\\[').replace('&', '\\&').replace('`', '\\`').replace('$', '\\$')[:-5] + '.m4a' _file_s = _file.replace(' ', '\\ ').replace("'", "\\'").replace(')', '\\)').replace('(', '\\(') \
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1 .replace(']', '\\]').replace('[', '\\[').replace('&', '\\&').replace('`', '\\`') \
if _active_processes >= cpu_count(): .replace('$', '\\$')
while _active_processes >= cpu_count(): _file_d = _file.replace(path.expanduser(source), path.expanduser(destination)).replace(' ', '\\ ') \
print(f"\nThere are already {cpu_count()} processes running...\n") .replace("'", "\\'").replace(')', '\\)').replace('(', '\\(').replace(']', '\\]') \
sleep(1) .replace('[', '\\[').replace('&', '\\&').replace('`', '\\`').replace('$', '\\$')[
_active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1 :-5] + '.m4a'
_i += 1 _active_processes = int(check_output('ps -C ffmpeg | wc -l', shell=True)) - 1
print(f"\n{_progress}% | \u001b[38;5;0;48;5;15mConverting {_file_s} to {_file_d}...\u001b[0m\n") if _active_processes >= cpu_count():
# get relevant ReplayGain info while _active_processes >= cpu_count():
try: 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")
# get relevant ReplayGain info
_audio = FLAC(f"{_file}") _audio = FLAC(f"{_file}")
if args.albumgain: if args.albumgain:
if _audio.get('REPLAYGAIN_ALBUM_GAIN'): if _audio.get('REPLAYGAIN_ALBUM_GAIN'):
@@ -89,27 +95,23 @@ def scan_destination_convert():
_rgpeak = float(_audio.get('replaygain_track_peak')[0]) _rgpeak = float(_audio.get('replaygain_track_peak')[0])
else: else:
_rgpeak = None _rgpeak = None
except FLACNoHeaderError: # determine ffmpeg arguments
print(f"[{_file}] Not a FLAC file, copying...") if args.bake and _rggain is not None:
copy(f"{_file}", f"{_file.replace(path.expanduser(source), path.expanduser(destination))}") _bake_args, _flac2pod_rg_tags = '-filter:a "volume=' + str(_rggain) + 'dB"', ''
_rggain, _rgpeak = None, None elif _rggain is not None and _rgpeak is not None:
# determine ffmpeg arguments _bake_args, _flac2pod_rg_tags = '', f"-metadata comment='FLAC2PODRG#{_rggain}#{_rgpeak}#'"
if args.bake and _rggain is not None: else:
_bake_args, _flac2pod_rg_tags = '-filter:a "volume=' + str(_rggain) + 'dB"', '' _bake_args, _flac2pod_rg_tags = '', ''
elif _rggain is not None and _rgpeak is not None: # generate the appropriate ffmpeg command
_bake_args, _flac2pod_rg_tags = '', f"-metadata comment='FLAC2PODRG#{_rggain}#{_rgpeak}#'" _cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:a aac -ab 256k {_bake_args} -map_metadata 0 " \
else: f"{_flac2pod_rg_tags} -aac_pns 0 -movflags +faststart -vn {_file_d} </dev/null"
_bake_args, _flac2pod_rg_tags = '', '' if _rggain is not None:
# generate the appropriate ffmpeg command print(f"\u001b[38;5;0;48;5;15mGain adjustment: {_rggain}dB\u001b[0m")
_cmd = f"screen -DmS flac2pod{_i} ffmpeg -i {_file_s} -c:a aac -ab 256k {_bake_args} -map_metadata 0 " \ else:
f"{_flac2pod_rg_tags} -aac_pns 0 -movflags +faststart -vn {_file_d} </dev/null" print(f"\u001b[38;5;0;48;5;88mNo ReplayGain data found!\u001b[0m")
if _rggain is not None: if args.stopifnogain:
print(f"\u001b[38;5;0;48;5;15mGain adjustment: {_rggain}dB\u001b[0m") s_exit(1)
else: Popen(_cmd, shell=True)
print(f"\u001b[38;5;0;48;5;88mNo ReplayGain data found!\u001b[0m")
if args.stopifnogain:
s_exit(1)
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:
print('\nPlease wait for the remaining conversions to complete...\n') print('\nPlease wait for the remaining conversions to complete...\n')
+21 -26
View File
@@ -1,14 +1,12 @@
#!/bin/bash #!/usr/bin/env bash
# This script packages flac2pod (from source) for Arch Linux. echo -e '\n\nthe value entered in this field will only affect the version reported to the package manager - the latest source is used regardless\n'
read -r -p "version number: " version
read -r -p "revision number: " revision
echo -e '\n\nThe value entered in this field will only affect the version reported to the package manager. The latest source is used regardless.\n' echo -e '\noptions (please enter the number only):'
read -r -p "Version number: " version echo -e '\n1. gitHub release tag\n2. local\n'
read -r -p "Revision number: " revision read -r -p "source (for build scripts): " source
echo -e '\nOptions (please enter the number only):'
echo -e '\n1. GitHub Release Tag\n2. Local\n'
read -r -p "Source (for build scripts): " source
if [ "$source" == "1" ]; then if [ "$source" == "1" ]; then
source='https://github.com/rwinkhart/flac2pod/releases/download/v$pkgver/flac2pod-$pkgver.tar.xz' source='https://github.com/rwinkhart/flac2pod/releases/download/v$pkgver/flac2pod-$pkgver.tar.xz'
@@ -16,22 +14,22 @@ else
source=local://flac2pod-"$version".tar.xz source=local://flac2pod-"$version".tar.xz
fi fi
# generic packaging
# Archive creation echo -e '\npackaging as generic...\n'
echo -e '\nPackaging as generic...\n' mkdir -p output/generictemp/usr/{bin,lib/flac2pod}
mkdir -p packages/archtemp/usr cp -r lib/. output/generictemp/usr/lib/flac2pod/
cp -r bin packages/archtemp/usr/ ln -s /usr/lib/flac2pod/flac2pod.py output/generictemp/usr/bin/flac2pod
cp -r share packages/archtemp/usr/ ln -s /usr/lib/flac2pod/flac2pod-flacgain.py output/generictemp/usr/bin/flac2pod-flacgain
tar -C packages/archtemp -cvf packages/flac2pod-"$version".tar.xz usr/ cp -r share output/generictemp/usr/
rm -rf packages/archtemp tar -C output/generictemp -cvJf output/flac2pod-"$version".tar.xz usr/
sha512="$(sha512sum packages/flac2pod-"$version".tar.xz | awk '{print $1;}')" rm -rf output/generictemp
sha512="$(sha512sum output/flac2pod-"$version".tar.xz | awk '{print $1;}')"
echo -e "\nsha512 sum:\n$sha512" echo -e "\nsha512 sum:\n$sha512"
echo -e "\nGeneric packaging complete.\n" echo -e "\ngeneric packaging complete\n"
# PKGBUILD creation # PKGBUILD creation
echo -e '\nGenerating PKGBUILD...' echo -e '\ngenerating PKGBUILD...'
echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com> echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com>
pkgname=flac2pod pkgname=flac2pod
pkgver="$version" pkgver="$version"
pkgrel="$revision" pkgrel="$revision"
@@ -40,14 +38,11 @@ url='https://github.com/rwinkhart/flac2pod'
arch=('any') arch=('any')
license=('GPL2') license=('GPL2')
depends=(ffmpeg flac python python-mutagen screen) depends=(ffmpeg flac python python-mutagen screen)
source=(\""$source"\") source=(\""$source"\")
sha512sums=('"$sha512"') sha512sums=('"$sha512"')
package() { package() {
tar xf flac2pod-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\"" tar xf flac2pod-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\""
} }
" > packages/PKGBUILD " > output/PKGBUILD
echo -e "\nPKGBUILD generated.\n" echo -e "\nPKGBUILD generated\n"