Nyttige scripts for å gjøre ting med musikksamlingen

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Jeg tenkte at det kanskje kunne være interessant med en tråd hvor vi samler opp forskjellige scripts (batch-filer, python scripts, ...) som gjør nyttige småjobber på et digitalt musikkarkiv. Det er alltid lettere å starte med noe som funker og så modifisere til eget bruk enn å begynne på bar bakke.

Som en lett oppvarming, en batchjobb som pakker ut alle HDCD-kodede flac-filer i en mappe til nye flac-filer i en undermappe. HDCD-formatet kan i prinsippet kode 20 bits dynamikk i en 16-bits fil, så vi lager 24-bits filer for å være sikker på at alt får plass. Visstnok skal dBpoweramp være i stand til å gjøre dette automatisk ved ripping, men av en eller annen uforklarlig grunn har aldri dette fungert hos meg, så det må gjøres etter ripping. Programmet som gjør selve jobben heter hdcd.exe og kan lastes ned herfra:
HDCD Software Decoder - Doom9's Forum
HDCD | Luke Skaff

Det er et par småting å passe på. hdcd.exe opererer på wav-filer, så vi må først pakke ut flac til wav, pakke ut HDCD-kodingen til en 24-bits wav-fil, og så konvertere den til flac igjen. Dette har en tendens til å gå hardt utover metadata, så vi tar vare på metadata i en egen tekstfil og henger dem på igjen til slutt. Det kan vi gjøre med programmene flac.exe og metaflac.exe. De finnes her:
FLAC - download

Riktignok må ReplayGain-verdiene beregnes på nytt helt til slutt, men det er en overkommelig jobb, så det tar vi ikke med i batchjobben i denne omgang. Da blir det slik:
[HR][/HR]@echo off
REM Batch job to unpack 16-bit HDCD files to 24-bit regular WAV files
REM Needs a final pass "by hand" to set correct replay gain and to add [HDCD] to album tag

IF NOT EXIST HDCD MKDIR HDCD
copy Folder.jpg HDCD\Folder.jpg

FOR %%A IN (*.flac) DO (
echo --------------
echo %%A
C:\Programfiler\FLAC\metaflac.exe --export-tags-to="HDCD\temp.txt" "%%A"
C:\Programfiler\FLAC\flac.exe -d -f -o "HDCD\temp1.wav" "%%A"
C:\Programfiler\HDCD\hdcd.exe -o "HDCD\temp2.wav" "HDCD\temp1.wav"
del "HDCD\temp1.wav"
C:\Programfiler\FLAC\flac.exe -5 -f -o "HDCD\%%~nA.flac" "HDCD\temp2.wav"
del "HDCD\temp2.wav"
C:\Programfiler\FLAC\metaflac.exe --import-tags-from="HDCD\temp.txt" --import-picture-from=Folder.jpg "HDCD\%%~nA.flac"
del "HDCD\temp.txt"​
)
[HR][/HR]
Den kodebiten lagres til en fil, f eks deHDCD.bat, og kjøres ved å dobbeltklikke på det ikonet i en vanlig Windows-mappe. Dette er vel ikke helt best practice-koding, ettersom adressen til de forskjellige programmene er hardkodet heller enn hentet fra environment-variabler, men det funker for meg.
 
Sist redigert:

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Dersom du ønsker å legge til [HDCD] til album-tagen så kan du såpne temp.txt fila di, finne album-tagen og appende " [HDCD]" og dermed legge til denne som en del av scriptet. Python er spesielt god på slikt.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Jeg har forøvrig et bash-script som jeg benytter for all inkommende FLAC. Dette er imidlertid dratt ganske mye lenger enn en liten "quick fix" siden det benyttes igjen og igjen og fungerer som en viktig integritetssjekk og arbeidsbesparende prosess hos meg. Det spørs om dette egentlig har noen nytteverdi for andre, spesielt fordi det også er rettet mot Linux som platform.

Scriptet går gjennom en mappestruktur med FLAC-filer, reencoder dem enten alle som en, alternativt sjekker versjonen de er encodet med for så å kun reenkode de som ikke er siste versjon. Du kan som et siste valg bare kjøre en test for sjekke integriteten på filene.

I tillegg kverner scriptet gjennom tags når filen uansett reenkodes med et tilhørende python script som automatiserer et par ting:
- Fjerner alle tags som ikke står i listen over tags du ønsker å ha i biblioteket for å unngå tvetydige tags og feil informasjon i biblioteker, selv om dine primære tags er satt korrekt.
- Korrigerer åpenbare feil som ekstra mellomrom på slutten/begynnelsen av en tag og tilsvarende
- Sørger for korrekt skrivemåte i henhold til ønsket visuell profil på en rekke ord. F.eks stor I, store romertall, for, in, with osv med liten forbokstav, liten bokstav på the med mindre setningen starter med The osv. Det er lett å legge til ting man ønsker å fikse på som er såpass generisk at det ikke gir en masse uønskede variasjoner når språket f.eks blir norsk på låttitler.

Scriptet benytter så mange prosesser du ønsker at det skal benytte så du kan f.eks kjøre fire parallelle reencodings-prosesser om du har en quad core. Dette øker hastigheten på eksekveringen drastisk.

I tillegg har jeg et script som er livsfarlig som jeg anbefaler at dere holder dere unna, som går gjennom en mappestruktur og sørger for at kun de filene jeg vil at skal være der er der. Det vil si *.flac og folder.jpg, og INGENTING annet. I tillegg vil scriptet ta alle folder.jpg filer som er over en viss størrelse, dvs 1000x1000, og krympe disse med en høykvalitets lanczos-algoritme. Dette gjøres fordi dette gir hurtigere respons i avspillerløsningen når man populerer album-browsing vinduer i f.eks MPad og JRiver.

Vedlagt er exporten fra trunk i SVN-repoet mitt. Det vil si siste gjeldende versjoner av scriptene. Jeg måtte zip-e tar.gz filen for å lov til å laste den opp her. Du må altså pakke ut både zip-filen og tar.gz for å komme til scriptene.
 

Vedlegg

Sist redigert:

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
De var ganske godt innpakket, ja, og så var det klassikeren med CR LF eller bare LF når ting flyttes mellom Linux og Windows. Men det gikk jo.

Du har tydeligvis automatisert mye som jeg fortsatt gjør manuelt, sånn som riktig valg av stor/liten forbokstav, fjerning av uvedkommende tags, osv. Jeg gjør det som en manuell workflow for å ha litt bedre kontroll med hva som skjer. Jeg gjør alltid en konvertering med dBpoweramp til slutt, både for å sette ReplayGain-tags og for å være sikker på at det er en konsistent versjon av flac-codec'en. Scriptet clean_flac_dir.sh ser bortimot livsfarlig ut, ja. Der ville nok jeg hardkodet eksakt hvilke mapper den får lov til å snuse på i selve scriptet.

På Windows er det ikke så veldig mye man kan få gjort i et shell script, og det lille man kan gjøre har en ubegripelig syntaks, så jeg har blitt fan av Python. Der bruker jeg versjon 2.7 fortsatt av hensyn til kompatibilitet med forskjellige biblioteker. For eksempel, hvis man funderer på om det er noen uutpakkede HDCD-filer på disken slik at det forrige scriptet er noe å ha, så kan man først lage et lite Python-script isFlacFileCDRez.py for å sjekke om filen er 16/44.1, og så kjøre hdcd.exe for å diagnostisere om det er HDCD eller ikke.

isFlacFileCDRez.py ser slik ut:
[hr][/hr]#!/usr/bin/env python
# -*- coding=latin_1 -*-

import os
import re
import string
import codecs
import sys
from mutagen.flac import FLAC

# takes one command line argument, assumed to be the name of a FLAC file,
# and checks if it is CD resolution or not. Returns 0 if CD, 1 if not.

audio = FLAC(sys.argv[1])
bits = audio.info.bits_per_sample
rate = audio.info.sample_rate

if (bits == 16 and rate == 44100):
sys.exit(0)​
else:
sys.exit(1)​
[hr][/hr]

Det scriptet kan kalles fra en batch-fil på denne måten:
[hr][/hr]@echo off
REM Batch job to identify 16-bit HDCD files

FOR /R %%A IN (*.flac) DO (
c:\Python27\python.exe isFlacFileCDRez.py "%%A"
IF NOT ERRORLEVEL 1 (
C:\Programfiler\FLAC\flac.exe -d -f -s -o C:\TEMP\temp.wav "%%A"
C:\Programfiler\HDCD\hdcd.exe -i -s C:\TEMP\temp.wav
IF NOT ERRORLEVEL 1 echo %%A​
)​
)

del C:\TEMP\temp.wav
pause "Press a key to continue..."
[hr][/hr]

Scriptet sjekker systematisk om hver 16/44.1 flac-fil er HDCD eller ikke. Hvis den er det, skriver den ut navnet på filen. Kommandoen FOR /R gjør at den kverner gjennom gjeldende mappe og alle undermapper. Lokasjonen for Python-interpreteren python.exe og programmene hdcd.exe og flac.exe er fortsatt hardkodet i scriptet. Vi kan lage en liten batch-fil med den teksten i, kalle den ScanHDCD.bat, og starte den fra et cmd-vindu som

cd /d Z:\media\Music
ScanHDCD > scanhdcd.txt


Da kverner den gjennom hele musikkbiblioteket og lager en fil, scanhdcd.txt, som inneholder navnet på alle flac-filer som inneholder HDCD-koding. Den filen blir slik:
[hr][/hr]
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\07 - Joni Mitchell - Rainy Night House.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\12 - Joni Mitchell - The Circle Game.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\04 - Joni Mitchell - Ladies of the Canyon.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\02 - Joni Mitchell - For Free.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\05 - Joni Mitchell - Willy.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\01 - Joni Mitchell - Morning Morgantown.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\11 - Joni Mitchell - Woodstock.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\06 - Joni Mitchell - The Arrangement.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\03 - Joni Mitchell - Conversation.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\09 - Joni Mitchell - Blue Boy.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\08 - Joni Mitchell - The Priest.flac
Z:\media\Music\Joni Mitchell\Ladies of the Canyon\10 - Joni Mitchell - Big Yellow Taxi.flac
.
.
.
[hr][/hr]

Det var noen overraskelser nedover i listen, selv om langtfra alle "HDCD-filene" brukte de funksjonene til noe nyttig. :)
 
Sist redigert:

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
På windows har man heldigvis nå fått powershell som et mer fullverdig alternativ til CMD. Jeg finner personlig at f.eks php, python, bash og cmd er relativt logiske språk, men når det gjelder powershell er det fremdeles RTFM som gjelder på annet enn de enkleste script for min del. Jeg har store problemer med å få syntaksen og funksjonene i powershell inn i fingrene. Jeg har laget mange powershell til administrative oppgaver i forbindelse med drift av Windows-systemer, men jeg har ingen Window-maskiner involvert i vedlikehold av mediabiblioteket.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Jeg har også et annet script som utfører en nyttig jobb her hjemme. Det er et script som kjøres automatisk på serveren og som konverterer FLAC-biblioteket til mp3 og som samtidig bevarer tags og kalkulerer ny gyldig replaygain med både track og album gain tilpasset mp3. Denne er kjekk å ha dersom man enkelt vil ha mp3-varianter av filene tilgjengelig for mobile enheter og tilsvarende.

Dette finnes selvsagt i ulike former fra før, men jeg utviklet mitt script fordi jeg synes tag-støtten ofte var svært mangelfull samt at scriptet mitt er laget noenlunde intelligent slik at kun endrede eller nye flac filer vil transkodes til mp3 ved neste gjennomkjøring, og scriptet vil også detektere om det er kun tagen som må oppdateres dersom FLAC-lyddataene er uendret. Poenget var å kunne kjøre dette direkte på mediaserveren, siden dette går mange ganger raskere enn å gjøre det samme over gigabitnettverket, spesielt siden scriptet kjører transkodingen i parallell på flere CPU-kjerner om ønskelig.

Sox er også involvert i kjeden, så om ønskelig kan man prosessere alle filene på ulikt vis mens de konverteres til mp3.

Det enkleste er å sjekke ut wiki-siden med informasjon om scriptet:

https://wiki.proikt.com/index.php/FLAC_to_MP3_mirror_sync

Per nå er v2.3.2 siste versjon. Jeg ha kjørt denne versjoner i mange måneder uten at nye bugs har dukket opp (det var en del småbugs i begynnelsen, spesielt med tanke på håndtering av filnavn og tags med sære spesialtegn, f.eks islandsk og kyrillisk). Scriptet er tilgjengelig på wikien, men for å dra opp nerdefaktoren litt i denne tråden, som jo må sies å være litt laber ( :) ), kan jeg jo lime inn koden her også:

Kode:
#!/bin/bash
#
# Author: Hans-Kristian Bakke
#
####

# Important: both paths must end with a trailing slash!
export musicdir="/srv/common/Media/Audio/FLAC/"
export mp3_destdir="/srv/common/Temp/MP3/"

# Set VBR quality for the mp3 files
export vbr_quality=0

# Configure tag options for eyeD3
export tag_options="-2 --to-v2.3 --encoding=utf16 --no-config"

# Number of concurrent processes to run. In addition the decoding and encoding already runs in parallel, but the lame encoding is much more demanding than the sox decoding.
# This value should normally be set to the count of your actual physical CPU cores.
concurrency=4

# Set to "yes" to show full output. This disables concurrency to avoid a visual mess.
export verbose="no"

####

# Check if the script is already running
for pid in $(pgrep "$(basename "$BASH_SOURCE")"); do
    if [[ $pid -ne $$ ]]; then
        echo "Script is already running. Exiting..."
        exit 0
    fi
done

# Make sure we have all the dependencies
for cmd in lame eyeD3 sox rsync metaflac; do
    command -v $cmd >/dev/null 2>&1 || { echo "'$cmd' is required, but not available. Exiting..." 1>&2; exit 1; }
done

# Text styling presets for prettier output
export red=$(tput bold && tput setaf 1)
export green=$(tput bold && tput setaf 2)
export yellow=$(tput bold && tput setaf 3)
export turquoise=$(tput bold && tput setaf 6)
export text_reset=$(tput sgr0)

# Make sure concurrency is set to a sane value
if [[ $concurrency -lt 1 || $verbose == "yes" ]]; then
    concurrency=1
fi

# Function that removes normal text output from script if verbose is not active
verbosity () {
    exec 3>&1 4>&2
    if ! [[ $verbose == "yes" ]]; then
        exec &>/dev/null
    fi
}

# Function for printing a message in non verbose mode
print_nv () {
    exec 1>&3
    echo "$@"
    verbosity
}

# Function for handling user aborts
abort () {
    print_nv "[ ${red}ABORT${text_reset} ]  Aborted by user!"
    rm -f $need_replaygain
    exit 1
}

# Function for syncing the library structure from source to destination directory
sync_library_structure () {
    if ! rsync -aviHH --stats --delete --filter='-p *.mp3' --exclude='*.[Ff][Ll][Aa][Cc]' "$1" "$2"; then
        echo "[ ${red}ERROR${text_reset} ]  Library structure sync failed!"
        exit 1
    else
        echo "[ ${green}STRUCTURE SYNC OK${text_reset} ]  Library structure sync from '$musicdir' to '$mp3_destdir' completed successfully"
    fi
    
    verbosity
}

# Function that encodes a mp3 file from a flac file, but only if the mp3 version does not exist or if the modify time is not the same
flac_to_mp3 () {
    local flac="$1"
    local mp3=$(echo "${flac/#"${musicdir}"/${mp3_destdir}}" | sed -r 's/\..{4}$/.mp3/')
    local timestamp_flac=$(stat -c "%Y" "$flac")
    local retag_only=false
    local tags_to_add=()
    local tag_options=($tag_options)
    
    # Create vorbis comment to id3v2 tag mapping
    declare -A tags
    tags["ALBUMARTIST"]="TPE2"
    tags["ALBUM ARTIST"]="TPE2"
    tags["ARTIST"]="TPE1"
    tags["ALBUM"]="TALB"
    tags["TRACKNUMBER"]="TRCK"
    tags["TITLE"]="TIT2"
    tags["DATE"]="TDRC"
    tags["GENRE"]="GENRE"
    tags["COMPOSER"]="TCOM"
    tags["CONDUCTOR"]="TPE3"
    tags["DISCNUMBER"]="TPOS"
    tags["TOTALDISCS"]="TXXX"
    tags["COMPILATION"]="TXXX"
    tags["WORK"]="TXXX"
    tags["FLAC_MD5"]="TXXX"

    if [[ -f $mp3 ]]; then
        local timestamp_mp3=$(stat -c "%Y" "$mp3")
        
        if [[ $timestamp_mp3 == $timestamp_flac ]]; then
            print_nv "[ ${green}UP-TO-DATE${text_reset} ]  $mp3"
            return
        elif [[ $timestamp_mp3 == $(( $timestamp_flac + 1 )) ]]; then
            print_nv "[ ${yellow}REPLAYGAIN MISSING${text_reset} ]  $mp3"
            echo "$mp3" >> $need_replaygain
            return
        else
            print_nv "[ ${yellow}CHANGED${text_reset} ]  $mp3"
            if [[ $(metaflac --show-md5sum "$flac") == $(eyeD3 -2 --no-config "$mp3" 2>&1 | grep -A 1 'FLAC_MD5' | tail -n 1) ]]; then
                retag_only=true
            else
                rm -f "$mp3"
            fi
        fi
    fi

    if $retag_only; then
        local replaygain_tags=$(eyeD3 -2 --no-config "$mp3" | grep -A 1 'replaygain_' | sed -r 's/^.*\s(r.*)\]$/--user-text-frame=\"\1:/g; s/([^|-][0-9\.]+).*/\1\" /g' | tr -d '\n')
        eyeD3 --remove-all --no-config "$mp3"
        tags_to_add+=($replaygain_tags)
    else
        set -o pipefail
        if ! sox -S "$flac" -t .wav -c 2 - rate -h 44100 | lame -V $vbr_quality --noreplaygain - "$mp3"; then
            print_nv "[ ${red}ERROR${text_reset} ]  Flac to mp3 encode failed for $flac"
            return
        fi
    fi
    
    local flac_tag=$(metaflac --export-tags-to=- "$flac")

    for tag in "${!tags[@]}"; do
        if [[ $tag == "FLAC_MD5" ]]; then
            tag_data=$(metaflac --show-md5sum "$flac")
        else
            tag_data=$(echo "$flac_tag" | sed -r 's/\$|`|\"/\\&/g' | awk 'tolower($0) !~ /^'"${tag,,}"'=/ {next} {sub(/.*=/, "", $0)} NF {if (x == "") x = $0; else x = x" / "$0} END {print x}')
        fi

        if [[ $tag_data == "" ]]; then
            continue
        fi

        if [[ ${tags[$tag]} == "GENRE" ]]; then
            tags_to_add+=("--genre=\"$tag_data\"")
        elif [[ ${tags[$tag]} == "TXXX" ]]; then
            tags_to_add+=("--user-text-frame=\"${tag}:$tag_data\"")
        else
            tags_to_add+=("--text-frame=\"${tags[$tag]}:$tag_data\"")
        fi
    done

    if [[ ${#tags_to_add[@]} -ne 0 ]]; then
        if eval eyeD3 ${tag_options[@]} ${tags_to_add[@]} "$(printf '%q' "$mp3")"; then
            if $retag_only; then
                if [[ $(echo "$replaygain_tags" | grep -E -o 'replaygain_reference_loudness|replaygain_track_gain|replaygain_track_peak' | wc -l) -lt 3 ]]; then
                    echo "$mp3" >> $need_replaygain
                    touch -d @$(( $timestamp_flac + 1 )) "$mp3"
                else
                    touch -d @$timestamp_flac "$mp3"
                fi
                print_nv "[ ${turquoise}RETAG OK${text_reset} ]  $mp3"
            else
                echo "$mp3" >> $need_replaygain
                touch -d @$(( $timestamp_flac + 1 )) "$mp3"
                print_nv "[ ${turquoise}FLAC -> MP3 OK${text_reset} ]  $mp3"
            fi
        else
            print_nv "[ ${red}ERROR${text_reset} ]  Tagging failed for $mp3"
        fi
    fi
}

# Function that finds mp3 files with no flac equivalent
remove_if_no_flac () {
    local valid_mp3_files=$(mktemp)
    local mp3_files=$(mktemp)
    
    cd "$musicdir"
    find . -type f -iname '*.flac' | sed -r 's/\..{4}$/.mp3/' > $valid_mp3_files
    cd "$mp3_destdir"
    find . -type f -name '*.mp3' > $mp3_files
    grep -FZvf $valid_mp3_files $mp3_files | xargs -0 -d "\n" -r -n 1 -P $concurrency bash -c 'delete_mp3 "$@"' --
    rm -f $valid_mp3_files $mp3_files
}

# Function that deletes a mp3 file. Expects a relative path.
delete_mp3 () {
    local mp3="${mp3_destdir}${1#./}"
    print_nv "[ ${yellow}DELETE${text_reset} ]  $mp3"
    rm -f "$mp3"
}

# Function that calculates replay gain for a directory with mp3s while preserving timestamps
add_replaygain () {
    local mp3_dir="$1"
    local timestamps=()
    local tag_options=($tag_options)
    
    cd "$mp3_dir"
    for mp3 in *.mp3; do
        local timestamp_mp3=$(stat -c "%Y" "$mp3")
        if ! grep -F "${mp3_dir}/${mp3}" $need_replaygain; then
            eyeD3 -2 --no-config --user-text-frame="replaygain_reference_loudness:" --user-text-frame="replaygain_track_gain:" --user-text-frame="replaygain_track_peak:" --user-text-frame="replaygain_album_gain:" --user-text-frame="replaygain_album_peak:" "$mp3" > /dev/null 2>&1
            timestamps+=($(( $timestamp_mp3 + 1 )))
        else
            timestamps+=($timestamp_mp3)
        fi
    done

    if ! mp3gain -s i *.mp3; then
        print_nv "[ ${red}REPLAYGAIN FAILED${text_reset} ]  $mp3_dir"
    fi

    # mp3gain always converts tags to id3v2.4 when using id3v2 tags. Process the tags using eyeD3 to enforce correct tag settings
    eyeD3 ${tag_options[@]} --remove-frame="RVA2" --user-text-frame="MP3GAIN_ALBUM_MINMAX:" --user-text-frame="MP3GAIN_MINMAX:" *.mp3 > /dev/null 2>&1

    local index=0
    for mp3 in *.mp3; do
        touch -d @$(( ${timestamps[$index]} - 1 )) "$mp3"
        print_nv "[ ${turquoise}REPLAYGAIN OK${text_reset} ]  ${mp3_dir}/${mp3}"
        index=$(( $index + 1 ))
    done
}

# Initialize
export -f print_nv
export -f verbosity
export need_replaygain=$(mktemp)

# Stage 1: Sync all files except flac-files while preventing deletion of mp3-files in the destination which obviously do not match any files in the source directory
sync_library_structure "$musicdir" "$mp3_destdir"

# Stage 2: Reencode all flac files to mp3
trap 'abort' SIGINT SIGTERM
export -f flac_to_mp3
find "$musicdir" -type f -iname '*.flac' -print0 | xargs -0 -r -n 1 -P $concurrency bash -c 'flac_to_mp3 "$@"' --

# Stage 3: Remove mp3s without a flac equivalent
export -f delete_mp3
remove_if_no_flac

# Stage 4: Calculate replaygain for all files
export -f add_replaygain
cat $need_replaygain | sed 's/\/[^\/]*$//' | sort -u | xargs -r -d "\n" -n 1 -P $concurrency bash -c 'add_replaygain "$@"' --

# Clean up
rm -f $need_replaygain
trap - SIGINT SIGTERM
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Hvilken del av FOR /R %%A IN (*.flac) DO er det du ikke forstår? :)
Jeg høyner med denne fra mp3-mirror.sh:
Kode:
tag_data=$(echo "$flac_tag" | sed -r 's/\$|`|\"/\\&/g' | awk 'tolower($0) !~ /^'"${tag,,}"'=/ {next} {sub(/.*=/, "", $0)} NF {if (x == "") x = $0; else x = x" / "$0} END {print x}')
Jeg har sett over denne forferdelige linjen igjen og igjen og dette representerer utrolig nok den optimaliserte versjonen. Ikke et eneste tegn kan fjernes uten at det blir tull. Det var når jeg strevde med dette at jeg skulle ønske jeg valgte python i stedet for bash, siden dette ville sett mye penere og mer forståelig ut der :)
 

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Interessant script. Jeg blir nesten nostalgisk, for jeg gjorde mye rart med sed og awk tidlig på 90-tallet. De litt større jobbene brukte jeg gjerne perl til. Blant annet lagde jeg meg en virtuell supercomputer i perl, hvor en Linux-maskin fordelte simuleringsjobber på et cluster av Sun arbeidsstasjoner og samlet sammen resultatene fra alle replikasjonene over nettverket. En såkalt "slopsucker", siden hver simulering kjørte i bakgrunnen med lav prioritet og var tilnærmet usynlig for den som eventuelt jobbet på maskinen.

Jeg har også et script som vedlikeholder portable versjoner av flac-biblioteket, men det virker på litt annen måte. Jeg bruker 16 bits/44.1 kHz AAC som det portable formatet, ikke mp3. Så bruker jeg dBpoweramp's coreconverter.exe som motor i konverteringen, slik at jeg kan bruke de DSP-funksjonene som ligger der. Den kaller i sin tur Nero for selve konverteringen. Dessverre betyr dette at scriptet må kjøre på PC'en i stedet for på ReadyNAS'en, så det blir mye skyfling av data frem og tilbake over nettverket. Jeg har heller ikke lagd en funksjon for å slette uaktuelle AAC-filer, men gjør dette for hånd ved behov. Og så er det et python-script MakeAAC.py, ikke bash:

Kode:
#!/usr/bin/env python
# -*- coding=latin_1 -*-

import os
import sys
import re
import string
import codecs
import subprocess
import unicodedata
import shutil
from mutagen.flac import FLAC

tgthead = "z:\media\AAC"
badchars= re.compile(r'[^A-Za-z0-9_ ]+|^ | $|^$')

def deScandify(s):
        # replace Scandinavian and German characters by ASCII versions
        s = re.sub("Æ", "AE", s)
        s = re.sub("æ", "ae", s)
        s = re.sub("Ø", "O", s)
        s = re.sub("ø", "o", s)
        s = re.sub("Å", "A", s)
        s = re.sub("å", "a", s)
        s = re.sub("Ö", "O", s)
        s = re.sub("ö", "o", s)
        return s

filecounter = 0
print "Scanning for new or changed files..."
for root, dirs, files in os.walk("."):
	for name in files:
		if re.search("flac$", name):
                        filecounter += 1
                        sys.stdout.write(str.format("\r{0:0>6}", filecounter))
                        sys.stdout.flush()
                        
			flacfilename = '{0}\{1}'.format(root, name)
			audio = FLAC(flacfilename)

                        if "artist" in audio:
                                artist = audio["artist"]
                                sartist = unicodedata.normalize('NFKD', unicode(artist[0])).encode('latin-1', 'ignore')
                                sartist = deScandify(sartist)
                                sartist = badchars.sub("", sartist)
                        else:
                                sartist = "Unknown"

			if "albumartist" in audio:
                                albumartist = audio["albumartist"]
                                salbumartist = unicodedata.normalize('NFKD', unicode(albumartist[0])).encode('latin-1', 'ignore')
                                salbumartist = deScandify(salbumartist)
                                salbumartist = badchars.sub("", salbumartist)
                        else:
                                salbumartist = sartist
                                
                        if "compilation" in audio:
                                compilation = audio["compilation"]
                                scomp = unicodedata.normalize('NFKD', unicode(compilation[0])).encode('latin-1', 'ignore')
                                if scomp == "1" and not "albumartist" in audio:
                                        salbumartist = "Various Artists"

			if "album" in audio:
                                album = audio["album"]
                                salbum = unicodedata.normalize('NFKD', unicode(album[0])).encode('latin-1', 'ignore')
                                salbum = deScandify(salbum)
                                salbum = badchars.sub("", salbum)
                        else:
                                salbum = "Unknown"
                                
			if "title" in audio:
                                title = audio["title"]
                                stitle = unicodedata.normalize('NFKD', unicode(title[0])).encode('latin-1', 'ignore')
                                stitle = deScandify(stitle)
                                stitle = badchars.sub("", stitle)
                        else:
                                stitle = "Unknown"

			if "tracknumber" in audio:
                                track = audio["tracknumber"]
                                strack = track[0].encode("latin-1", "ignore")
                                strack = badchars.sub("", strack)
                        else:
                                strack = "xx"

                        albumartistdir = os.path.join(tgthead, salbumartist)
			albumartistdir = " ".join(albumartistdir.split())
                        if not os.path.exists(albumartistdir):
                                os.mkdir(albumartistdir)

			albumdir = os.path.join(albumartistdir, salbum)
			albumdir = " ".join(albumdir.split())
                        if not os.path.exists(albumdir):
                                os.mkdir(albumdir)

			trackname = str.format("{0:0>2} - {1} - {2}.m4a", strack, sartist, stitle)
                        trackname = " ".join(trackname.split())
                        tgtpath = os.path.join(albumdir, trackname)

                        doconvert = False
                        if not os.path.exists(tgtpath):
                                doconvert = True
                        else:
                                srctime = os.path.getmtime(flacfilename)
                                tgttime = os.path.getmtime(tgtpath)
                                if srctime > tgttime:
                                        doconvert = True

                        if doconvert:
                                sys.stdout.write("\n")
                                tmpname = os.path.join("C:\TEMP",trackname)

                                cmdline = str.format('"C:\\Programfiler\\Illustrate\\dBpoweramp\\coreconverter.exe" -infile=\"{0}\" -outfile=\"{1}\" -convert_to=\"m4a Nero (AAC)\" -dspeffect1=\"ReplayGain (Apply)= -mode={{qt}}1{{qt}} -noclac -activedb={{qt}}0{{qt}} -nonactivedb={{qt}}0{{qt}}\" -dspeffect2=\"Bit Depth=-depth={{qt}}16{{qt}}\" -dspeffect3=\"Resample=-frequency={{qt}}44100{{qt}}\" -cli_encoder=\"C:\Programfiler\Illustrate\dBpoweramp\encoder\m4a Nero (AAC)\neroAacEnc.exe\" -cli_cmd=\"-q 0.85 -ignorelength -if - -of {{qt}}[outfile]{{qt}}\"',\
                                          flacfilename, tmpname)
                                subprocess.check_call(cmdline, shell=True)
                                print "Copying to ", albumdir
                                shutil.copy(tmpname, tgtpath)
                                os.remove(tmpname)
                                sys.stdout.write("\n")
                                sys.stdout.flush()
Mye av koden går med til å fjerne spesialtegn og sære bokstaver fra filnavnet. Scriptet viser også en løpende teller på skjermen for hvor mange filer den har sett på, sånn at det ikke ser ut som om det henger halve dagen.

Av en eller annen grunn får ikke Nero med seg den ordren om "-q 0.85" (very high quality), så den konverterer til normale -q 0.45 (medium quality) i stedet. Det blir likevel forbausende bra. Jeg tror forklaringen på det er at coreconverter.exe først gjør en ReplayGain (Apply) og tilpasser nivået på hver fil i henhold til lagrede ReplayGain-tags før selve konverteringen skjer. Da får Nero mye headroom å jobbe i. De første AAC-filene jeg lagde låt litt hardt på iPhone, noe jeg trodde var en begrensning i hardware, men filene som kommer ut av dette scriptet har ikke den hardheten, såvidt jeg kan høre.

Uansett, det scriptet kan kalles fra en wrapper i cmd, f eks MakeAAC.bat:
[hr][/hr]REM Batch job to create AAC copies of FLAC files
cd /d z:\media\Music
C:\Python27\python.exe MakeAAC.py
pause
[hr][/hr]

Så er det bare å klikke på ikonet for den batch-filen og la scriptet jobbe over natten.
 
Sist redigert:

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
Hvilken del av FOR /R %%A IN (*.flac) DO er det du ikke forstår? :)
Jeg høyner med denne fra mp3-mirror.sh:
Kode:
tag_data=$(echo "$flac_tag" | sed -r 's/\$|`|\"/\\&/g' | awk 'tolower($0) !~ /^'"${tag,,}"'=/ {next} {sub(/.*=/, "", $0)} NF {if (x == "") x = $0; else x = x" / "$0} END {print x}')
Jeg har sett over denne forferdelige linjen igjen og igjen og dette representerer utrolig nok den optimaliserte versjonen. Ikke et eneste tegn kan fjernes uten at det blir tull. Det var når jeg strevde med dette at jeg skulle ønske jeg valgte python i stedet for bash, siden dette ville sett mye penere og mer forståelig ut der :)
Den där raden har jag slitit med också:cool:.
Laddade ner ditt script för ett tag sedan med avsikt att köra det på min NAS, ReadyNAS Ultra. Lyckades installera alla beroenden
efter en del pyssel men just den här raden i scriptet ville inte fungera i den version av bash som används i NAS:en. Försökte skriva
om eftersom det kändes vanskligt att uppdatera bash. Lyckades aldrig få till scriptet till 100% så till slut gav jag mig på att uppdatera bash
samt en del beroenden till detta. Resultatet blev att scriptet fungerade men NAS:en blev ostabil:cool:...inte helt optimalt. Troligen var jag lite
oförsiktig vid något tillfälle med de sources jag hade för apt.

Slutade med att jag fick installera om OS:et på nytt...no big-deal, går relativt fort och enkelt att få upp igen med bibehållna shares.

Någon regnig dag i sommar skall jag ge mig på det igen:)
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Det kan være at NASen ble ustabil som en konsekvens av at både disk og CPU får virkelig juling når skriptet kjører. Supermicro-serveren min begynner å hyle som et skremt dyr når dette scriptet setter i gang, og da først og fremst på grunn av parallelliseringen som medfører at ingen del av serverens I/O system forblir upint.

Uansett så har jeg aldri testet scriptet på en NAS. Avhengighetene er først og fremst tilpasset Debian Wheezy (dvs nåværende stable) og senere. NASer har jo ofte litt eldre og tilpasset programvare.
 
Sist redigert:

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Fant du forøvrig ut hva som var problemet? Jeg bruker i hvertfall én såkalt "bashism" der i form av ${tag,,} som automatisk gjør $tag variabelen til lowercase uten å endre selve variabelen. Dette er ting som kan skrives om dersom dette gir scriptet høyere kompatibilitet med eldre bash-varianter. Hvis du klarer å peke konkret på hva som var problemet så kan jeg se på saken.
 

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
Det var just denna del, ${tag,,}, som var problemet. Höll på ett tag utan att få till något motsvarande som fungerade.
ReadyNas Ultra kör ju en ganska gammal version, Debian etch, om jag inte minns fel.

Att den blev ostabil märktes först i web-interfacet, inget svar från många dialoger.
Hade på känn att den inte skulle klara en reboot :cool:...vilket den inte gjorde när jag sedan testade.
Fick en kernel-panic redan vid shutdown och bootade aldrig så långt att nät-interfacet gick upp och ingen console
finns ju tillgänglig. Blev en OS-reinstall och det var inte första gången...en ReadyNas mår bäst av att inte 'pillas' med,
men svårt att låta bli ibland :)
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
OK. Det er sannsynlivis fullt løsbart å finne en erstatning for ${tag,,}, selv om det blir litt mer kode. Jeg skal sjekke det opp når jeg kommer hjem.
 

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
OK. Det er sannsynlivis fullt løsbart å finne en erstatning for ${tag,,}, selv om det blir litt mer kode. Jeg skal sjekke det opp når jeg kommer hjem.
Det är inget som brådskar ;) Tänkte testa detta vidare när jag fått ny NAS i hus, då kan jag laborera med ReadyNas:en utan att bli
sittandes utan musik vid ett eventuellt missöde. Även om det är hyfsat snabbt att komma på banan igen blir det ju ett avbrott.
En hel del pyssel med 3-e parts repos och det gäller att hålla tungan i rätt mun :)

Har inte bestämt mig riktigt än om vilken ny NAS jag skall välja. Kanske någon ur den nya generationens Readynas, alternativt bygga
något eget baserat på FreeNas(mest för nöjet av att ha något eget;) )
 

kanaris

Hi-Fi freak
Ble medlem
09.03.2010
Innlegg
1.756
Antall liker
1.660
Sted
Fetsund
Noen her som vet om en måte å generere en utskrivbar liste av biblioteket.

Tenker meg noe som Artist - Album - År.

Bruker Jriver og Squeezebox hvis det har noe å si. I tillegg er jeg grønn på data


mvh
 

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
Noen her som vet om en måte å generere en utskrivbar liste av biblioteket.

Tenker meg noe som Artist - Album - År.

Bruker Jriver og Squeezebox hvis det har noe å si. I tillegg er jeg grønn på data


mvh
Har inte sett att Jriver har något verktyg/plugin för det.
Jag använder mp3tag(freeware) och med det kan man exportera till olika format, t.ex. csv, html. Man kan också
välja vilken information som skall exporteras.
 

kanaris

Hi-Fi freak
Ble medlem
09.03.2010
Innlegg
1.756
Antall liker
1.660
Sted
Fetsund
Noen her som vet om en måte å generere en utskrivbar liste av biblioteket.

Tenker meg noe som Artist - Album - År.

Bruker Jriver og Squeezebox hvis det har noe å si. I tillegg er jeg grønn på data


mvh
Har inte sett att Jriver har något verktyg/plugin för det.
Jag använder mp3tag(freeware) och med det kan man exportera till olika format, t.ex. csv, html. Man kan också
välja vilken information som skall exporteras.
Har jo mp3tag. Da får jeg sjekke den

Takker for svar.


mvh
 

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Ja, mp3tag har en "Export..."-kommando på filmenyen. Den bruker et filformat som heter .mte for å definere eksakt hva som skal eksporteres og i hvilket format. Det er nok den mest brukervennlige måten. Men det kan være nokså tidkrevende å åpne hele biblioteket samtidig i mp3tag bare for å kunne eksportere en liste med artist, album, år og tittel for hver sang, så jeg skrev et lite python-script for dette også. Da vil jeg også ha med ReplayGain-tag'ene for hver sang. Scriptet scanflac.py ser slik ut:

Kode:
#!/usr/bin/env python
# -*- coding=latin_1 -*-

import os
import re
import string
import codecs
from mutagen.flac import FLAC

print "flacfile\tartist\talbum\tgenre\tdate\treplaygain_album_gain\treplaygain_album_peak\ttitle\treplaygain_track_gain\treplaygain_track_peak"

for root, dirs, files in os.walk("."):
	for name in files:
		if re.search("flac$", name):
			flacfilename = '{0}\{1}'.format(root, name)
			audio = FLAC(flacfilename)
			
			if "artist" in audio:
                                artist = audio["artist"]
                                sartist = artist[0].encode("latin_1", "ignore")
                        else:
                                sartist = "Unknown"
                                
			if "album" in audio:
                                album = audio["album"]
                                salbum = album[0].encode("latin_1", "ignore")
                        else:
                                salbum = "Unknown"
                                
			if "genre" in audio:
                                genre = audio["Genre"]
                                sgenre = genre[0].encode("latin_1", "ignore")
                        else:
                                sgenre = "Unknown"
                                
			if "date" in audio:
                                date = audio["date"]
                                sdate = date[0].encode("latin_1", "ignore")
                        else:
                                sdate = "Unknown"
                        
			if "replaygain_album_gain" in audio:
                                rgag = audio["replaygain_album_gain"]
                                srgag = re.sub(" dB", "", rgag[0])
                        else:
                                srgag = "Unknown"
                                
			if "replaygain_album_peak" in audio:
                                rgap = audio["replaygain_album_peak"]
                                srgap = re.sub(" dB", "", rgap[0])
                        else:
                                srgap = "Unknown"
                         
			if "title" in audio:
                                title = audio["title"]
                                stitle = title[0].encode("latin_1", "ignore")
                        else:
                                stitle = "Unknown"

			if "replaygain_track_gain" in audio:
                                rgtg = audio["replaygain_track_gain"]
                                srgtg = re.sub(" dB", "", rgtg[0])
                        else:
                                srgtg = "Unknown"
                                
			if "replaygain_track_peak" in audio:
                                rgtp = audio["replaygain_track_peak"]
                                srgtp = rgtp[0].encode("latin_1", "ignore")
                        else:
                                srgtp = "Unknown"
			
			print flacfilename, '\t', sartist, '\t', \
                              salbum, '\t', sgenre, '\t', sdate, '\t', \
                              srgag, '\t', srgap, '\t', stitle, '\t', \
                              srgtg, '\t', srgtp
Ganske enkelt, egentlig. Scriptet skriver ut en linje med kolonneoverskrifter. Deretter rusler det gjennom hele mappestrukturen og ser på hver enkelt flac-fil. Det plukker ut info fra tags og formatterer dem som ryddige tekststrenger eller setter inn ordet "Unknown" hvis den tag-verdien ikke finnes. For hver fil skriver den ut en linje med filnavn, artist, album, genre, år, album gain, album peak, track, track gain og track peak. De enkelte dataverdiene er skilt med tabs på hver linje.

Det scriptet kan også puttes inn i en wrapper som det forrige, en enkel batchjobb (cmd) som starter det og redirigerer output til en fil. Deretter kan den tekstfilen importeres i Excel og sorteres på alle tenkelige måter. Dessuten kan man lage diverse grafer, som for eksempel denne med anslått dynamikk for 40000 sanger sortert etter årstall:

Microsoft Excel - scanflac.xls_4.jpg


Joda, den gjennomsnittlige nyutgitte CD'en har en god del mindre dynamikk enn hva som fantes på de gamle 78-steinkakene fra før microgroove LP ble oppfunnet i 1948...

En annen ting man kan gjøre med den filen er å opprette pivottabeller i Excel og lære ting om musikksamlingen sin man kanskje ikke visste. Jeg ser at jeg har flest spor med Bob Dylan (563), etterfulgt av Rolling Stones (551), The Beatles (478) og Bruce Springsteen (471). Derimot er det ca 2100 artister med bare ett spor hver. En del av dem er nok sporadiske stavefeil i artistnavn, men likevel var det ganske mange.
 
Sist redigert:

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Noen her som vet om en måte å generere en utskrivbar liste av biblioteket.

Tenker meg noe som Artist - Album - År.

Bruker Jriver og Squeezebox hvis det har noe å si. I tillegg er jeg grønn på data


mvh
Hvis du har noenlunde kontroll på mappestruktur og filnavn, og ikke trenger å sortere så veldig så er kanskje det aller enkleste bare å kjøre windows-kommandoen "tree".

Kode:
tree M:\Audio\Flac
Folder PATH listing for volume Media
Volume serial number is 7396-ED4E
M:\AUDIO\FLAC
├───A
│   ├───The Allman Brothers Band
│   │   ├───1973 - Brothers and Sisters
│   │   ├───2003 - Hittin' the Note
│   │   └───1971 - At Fillmore East
│   ├───ATB
│   │   ├───2005 - Seven Years 1998-2005
│   │   ├───2000 - Two Worlds
│   │   │   ├───CD2 (The Relaxing World)
│   │   │   └───CD1 (The World of Movement)
│   │   ├───2002 - Dedicated (Special Limited Edition)
│   │   │   ├───CD1
│   │   │   └───CD2 (Bonus CD)
│   │   ├───1999 - Movin' Melodies
│   │   ├───2003 - Addicted to Music
│   │   └───2007 - Trilogy
│   │       ├───CD1
│   │       └───CD2
│   ├───Active Child
│   │   └───2011 - You Are All I See
│   ├───Admiral Sir Cloudesley Shovell
│   │   └───2012 - Don't Hear it...Fear It!
│   ├───Anastacia
│   │   ├───2001 - Freak of Nature
│   │   └───2000 - Not That Kind
│   ├───Aerosmith
│   │   ├───1973 - Aerosmith
│   │   ├───1997 - Nine Lives
│   │   ├───1987 - Permanent Vacation
│   │   ├───1974 - Get Your Wings
│   │   ├───1977 - Draw the Line
│   │   ├───1979 - Night in the Ruts
│   │   ├───1975 - Toys in the Attic
│   │   ├───2004 - Honkin' on Bobo
│   │   ├───1989 - Pump
│   │   ├───1982 - Rock in a Hard Place
│   │   ├───1993 - Get a Grip
│   │   ├───1985 - Done with Mirrors
│   │   └───1976 - Rocks
│   ├───Antonio Forcione
│   │   └───2000 - Live!
│   ├───Annie Lennox
│   │   ├───1992 - Diva
│   │   └───2009 - The Annie Lennox Collection (Limited Edition)
│   │       ├───CD1
│   │       └───CD2
│   ├───Amy Macdonald
│   │   ├───2010 - A Curious Thing
osv....
Hvis du tar med argumentet /F får du med filnavn også:
Kode:
tree /F M:\Audio\Flac
Folder PATH listing for volume Media
Volume serial number is 7396-ED4E
M:\AUDIO\FLAC
├───A
│   ├───The Allman Brothers Band
│   │   ├───1973 - Brothers and Sisters
│   │   │       03 - Come and Go Blues.flac
│   │   │       05 - Southbound.flac
│   │   │       folder.jpg
│   │   │       07 - Pony Boy.flac
│   │   │       06 - Jessica.flac
│   │   │       02 - Ramblin' Man.flac
│   │   │       01 - Wasted Words.flac
│   │   │       04 - Jelly Jelly.flac
│   │   │
│   │   ├───2003 - Hittin' the Note
│   │   │       07 - Maydell.flac
│   │   │       04 - Woman Across the River.flac
│   │   │       10 - Instrumental Illness.flac
│   │   │       09 - Heart of Stone.flac
│   │   │       06 - Who to Believe.flac
│   │   │       03 - Desdemona.flac
│   │   │       02 - High Cost of Low Living.flac
│   │   │       01 - Firing Line.flac
│   │   │       folder.jpg
│   │   │       08 - Rockin' Horse.flac
│   │   │       11 - Old Friend.flac
│   │   │       05 - Old Before My Time.flac
│   │   │
│   │   └───1971 - At Fillmore East
│   │           06 - In Memory of Elizabeth Reed.flac
│   │           07 - Whipping Post.flac
│   │           04 - You Don't Love Me.flac
│   │           03 - Stormy Monday.flac
│   │           folder.jpg
│   │           01 - Statesboro Blues.flac
│   │           02 - Done Somebody Wrong.flac
│   │           05 - Hot 'Lanta.flac
│   │
│   ├───ATB
│   │   ├───2005 - Seven Years 1998-2005
│   │   │       15 - Let U Go.flac
│   │   │       01 - Humanity.flac
│   │   │       07 - Here with Me.flac
│   │   │       20 - 9pm ('Till I Come).flac
│   │   │       02 - Let U Go (2005 Reworked).flac
│   │   │       06 - Far Beyond.flac
│   │   │       13 - You're Not Alone.flac
│   │   │       12 - I Don't Wanna Stop.flac
│   │   │       14 - Hold You.flac
│   │   │       folder.jpg
│   │   │       16 - The Fields of Love.flac
│   │   │       10 - In Love with the DJ.flac
│   │   │       08 - Ecstasy.flac
│   │   │       09 - Marrakech.flac
│   │   │       03 - Believe in Me.flac
│   │   │       19 - Don't Stop.flac
│   │   │       18 - Killer.flac
│   │   │       11 - Long Way Home.flac
│   │   │       17 - The Summer.flac
│   │   │       04 - Trilogie Part 2.flac
│   │   │       05 - Take Me Over.flac
osv...

Hvis du vil ha alt til en fil i mappen du står i kan du gjøre følgende:
Kode:
tree /F /A M:\Audio\Flac > Musikkbibliotek.txt
/A er for ASCII output, slik at linjene ser bedre ut i tekstfilen.

Merk at dette ikke er sammenlignbart med f.eks en csv-export i prosesserbarhet og tilsvarende. Men dersom behovet kun er å liste ut filer på en visuell måte så er dette en enkel måte.
 

kanaris

Hi-Fi freak
Ble medlem
09.03.2010
Innlegg
1.756
Antall liker
1.660
Sted
Fetsund
Noen her som vet om en måte å generere en utskrivbar liste av biblioteket.

Tenker meg noe som Artist - Album - År.

Bruker Jriver og Squeezebox hvis det har noe å si. I tillegg er jeg grønn på data


mvh
Hvis du har noenlunde kontroll på mappestruktur og filnavn, og ikke trenger å sortere så veldig så er kanskje det aller enkleste bare å kjøre windows-kommandoen "tree".

Kode:
tree M:\Audio\Flac
Folder PATH listing for volume Media
Volume serial number is 7396-ED4E
M:\AUDIO\FLAC
├───A
│   ├───The Allman Brothers Band
│   │   ├───1973 - Brothers and Sisters
│   │   ├───2003 - Hittin' the Note
│   │   └───1971 - At Fillmore East
│   ├───ATB
│   │   ├───2005 - Seven Years 1998-2005
│   │   ├───2000 - Two Worlds
│   │   │   ├───CD2 (The Relaxing World)
│   │   │   └───CD1 (The World of Movement)
│   │   ├───2002 - Dedicated (Special Limited Edition)
│   │   │   ├───CD1
│   │   │   └───CD2 (Bonus CD)
│   │   ├───1999 - Movin' Melodies
│   │   ├───2003 - Addicted to Music
│   │   └───2007 - Trilogy
│   │       ├───CD1
│   │       └───CD2
│   ├───Active Child
│   │   └───2011 - You Are All I See
│   ├───Admiral Sir Cloudesley Shovell
│   │   └───2012 - Don't Hear it...Fear It!
│   ├───Anastacia
│   │   ├───2001 - Freak of Nature
│   │   └───2000 - Not That Kind
│   ├───Aerosmith
│   │   ├───1973 - Aerosmith
│   │   ├───1997 - Nine Lives
│   │   ├───1987 - Permanent Vacation
│   │   ├───1974 - Get Your Wings
│   │   ├───1977 - Draw the Line
│   │   ├───1979 - Night in the Ruts
│   │   ├───1975 - Toys in the Attic
│   │   ├───2004 - Honkin' on Bobo
│   │   ├───1989 - Pump
│   │   ├───1982 - Rock in a Hard Place
│   │   ├───1993 - Get a Grip
│   │   ├───1985 - Done with Mirrors
│   │   └───1976 - Rocks
│   ├───Antonio Forcione
│   │   └───2000 - Live!
│   ├───Annie Lennox
│   │   ├───1992 - Diva
│   │   └───2009 - The Annie Lennox Collection (Limited Edition)
│   │       ├───CD1
│   │       └───CD2
│   ├───Amy Macdonald
│   │   ├───2010 - A Curious Thing
osv....
Hvis du tar med argumentet /F får du med filnavn også:
Kode:
tree /F M:\Audio\Flac
Folder PATH listing for volume Media
Volume serial number is 7396-ED4E
M:\AUDIO\FLAC
├───A
│   ├───The Allman Brothers Band
│   │   ├───1973 - Brothers and Sisters
│   │   │       03 - Come and Go Blues.flac
│   │   │       05 - Southbound.flac
│   │   │       folder.jpg
│   │   │       07 - Pony Boy.flac
│   │   │       06 - Jessica.flac
│   │   │       02 - Ramblin' Man.flac
│   │   │       01 - Wasted Words.flac
│   │   │       04 - Jelly Jelly.flac
│   │   │
│   │   ├───2003 - Hittin' the Note
│   │   │       07 - Maydell.flac
│   │   │       04 - Woman Across the River.flac
│   │   │       10 - Instrumental Illness.flac
│   │   │       09 - Heart of Stone.flac
│   │   │       06 - Who to Believe.flac
│   │   │       03 - Desdemona.flac
│   │   │       02 - High Cost of Low Living.flac
│   │   │       01 - Firing Line.flac
│   │   │       folder.jpg
│   │   │       08 - Rockin' Horse.flac
│   │   │       11 - Old Friend.flac
│   │   │       05 - Old Before My Time.flac
│   │   │
│   │   └───1971 - At Fillmore East
│   │           06 - In Memory of Elizabeth Reed.flac
│   │           07 - Whipping Post.flac
│   │           04 - You Don't Love Me.flac
│   │           03 - Stormy Monday.flac
│   │           folder.jpg
│   │           01 - Statesboro Blues.flac
│   │           02 - Done Somebody Wrong.flac
│   │           05 - Hot 'Lanta.flac
│   │
│   ├───ATB
│   │   ├───2005 - Seven Years 1998-2005
│   │   │       15 - Let U Go.flac
│   │   │       01 - Humanity.flac
│   │   │       07 - Here with Me.flac
│   │   │       20 - 9pm ('Till I Come).flac
│   │   │       02 - Let U Go (2005 Reworked).flac
│   │   │       06 - Far Beyond.flac
│   │   │       13 - You're Not Alone.flac
│   │   │       12 - I Don't Wanna Stop.flac
│   │   │       14 - Hold You.flac
│   │   │       folder.jpg
│   │   │       16 - The Fields of Love.flac
│   │   │       10 - In Love with the DJ.flac
│   │   │       08 - Ecstasy.flac
│   │   │       09 - Marrakech.flac
│   │   │       03 - Believe in Me.flac
│   │   │       19 - Don't Stop.flac
│   │   │       18 - Killer.flac
│   │   │       11 - Long Way Home.flac
│   │   │       17 - The Summer.flac
│   │   │       04 - Trilogie Part 2.flac
│   │   │       05 - Take Me Over.flac
osv...

Hvis du vil ha alt til en fil i mappen du står i kan du gjøre følgende:
Kode:
tree /F /A M:\Audio\Flac > Musikkbibliotek.txt
/A er for ASCII output, slik at linjene ser bedre ut i tekstfilen.

Merk at dette ikke er sammenlignbart med f.eks en csv-export i sorterbarhet og tilsvarende. Men dersom behovet kun er å liste ut filer på en visuell måte så er dette en enkel måte.
Vil egentlig bare ha en liste over alle cd,ene mine. Har rippet alle og lagt de i mapper som Artist - Album. En mappe for hver cd.
Har sjekket mp3tag, og tror jeg kan få til det.

Tusen takk for gode tips. Må forresten uansettl legge alle inn i mp3tag. Det er jo mye jeg skulle gjort annerledes, sånn blir det når alt læres underveis.
Det er jo ca 12 000 spor. tar vel kanskje 10 minutter.
 

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
CMD i Windows är ju ganska begränsad men en del kan man göra med kommandot "dir" om man har en bra struktur på mappar och filnamn.

dir /S /B /A:-D /O:N
Listar katalog samt alla underkataloger, ingen summary-info, inga 'ensamma' bibliotek, sorterat på filnamn

K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\01 - Inertia.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\02 - Through the Shadows.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\03 - Song of the Blackest Bird.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\04 - Only One Who Waits.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\05 - Unsung.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\06 - Every Hour Wounds.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\07 - Decoherence.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\08 - Lay the Ghost to Rest.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\09 - Regain the Fire.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\10 - One for Sorrow.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2011 - One for Sorrow\folder.jpg
K:\media\Music\LossLess\Albums\I\Insomnium\2004 - Since the Day It All Came Down\01 - Nocturne.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2004 - Since the Day It All Came Down\02 - The Day It All Came Down.flac
K:\media\Music\LossLess\Albums\I\Insomnium\2004 - Since the Day It All Came Down\03 - Daughter of the Moon.flac

Skulle fungera att dirigera om output till fil och sedan importera i Excel med "\" som avgränsare
 

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Det er egentlig bare ens egen skrudde fantasi som begrenser hva man kan finne på med lydfiler når de først er lagret på harddisk. marsboer nevnte programmet SoX. Det er "the swiss army knife of sound processing programs". Dessuten er det lite, raskt og gratis, så man kan til og med ha det i avspillingskjeden. Det finnes FM-stasjoner som sender gjennom en digital pipeline med SoX for volumnormalisering, kompresjon og limiting før signalet D/A-konverteres og går på lufta.

Scriptene over gjør noen enkle ting med lydfilen, som f eks å pakke ut HDCD eller å konvertere fra flac til mp3 eller aac. Her er flere ideer til hva man kan finne på:

Tone/filter effects
allpass: RBJ all-pass biquad IIR filter
bandpass: RBJ band-pass biquad IIR filter
bandreject: RBJ band-reject biquad IIR filter
band: SPKit resonator band-pass IIR filter
bass: Tone control: RBJ shelving biquad IIR filter
equalizer: RBJ peaking equalisation biquad IIR filter
firfit+: FFT convolution FIR filter using given freq. response (W.I.P.)
highpass: High-pass filter: Single pole or RBJ biquad IIR
hilbert: Hilbert transform filter (90 degrees phase shift)
lowpass: Low-pass filter: single pole or RBJ biquad IIR
sinc: Sinc-windowed low/high-pass/band-pass/reject FIR
treble: Tone control: RBJ shelving biquad IIR filter​

Production effects
chorus: Make a single instrument sound like many
delay: Delay one or more channels
echo: Add an echo
echos: Add a sequence of echos
flanger: Stereo flanger
overdrive: Non-linear distortion
phaser: Phase shifter
repeat: Loop the audio a number of times
reverb: Add reverberation
reverse: Reverse the audio (to search for Satanic messages ;-)
tremolo: Sinusoidal volume modulation​

Volume/level effects
compand: Signal level compression/expansion/limiting
contrast: Phase contrast volume enhancement
dcshift: Apply or remove DC offset
fade: Apply a fade-in and/or fade-out to the audio
gain: Apply gain or attenuation; normalise/equalise/balance/headroom
loudness: Gain control with ISO 226 loudness compensation
mcompand: Multi-band compression/expansion/limiting
norm: Normalise to 0dB (or other)
vol: Adjust audio volume​

Editing effects
pad: Pad (usually) the ends of the audio with silence
silence: Remove portions of silence from the audio
splice: Perform the equivalent of a cross-faded tape splice
trim: Cuts portions out of the audio
vad: Voice activity detector​

Mixing effects
channels: Auto mix or duplicate to change number of channels
divide+: Divide sample values by those in the 1st channel (W.I.P.)
remix: Produce arbitrarily mixed output channels
swap: Swap stereo channels​

Pitch/tempo effects
bend: Bend pitch at given times without changing tempo
pitch: Adjust pitch (= key) without changing tempo
speed: Adjust pitch & tempo together
stretch: Adjust tempo without changing pitch (simple alg.)
tempo: Adjust tempo without changing pitch (WSOLA alg.)​

Mastering effects
dither: Add dither noise to increase quantisation SNR
rate: Change audio sampling rate​

Specialised filters/mixers
deemph: ISO 908 CD de-emphasis (shelving) IIR filter
earwax: Process CD audio to best effect for headphone use
noisered: Filter out noise from the audio
oops: Out Of Phase Stereo (or `Karaoke') effect
riaa: RIAA vinyl playback equalisation​

Analysis `effects'
noiseprof: Produce a DFT profile of the audio (use with noisered)
spectrogram: graph signal level vs. frequency & time (needs `libpng')
stat: Enumerate audio peak & RMS levels, approx. freq., etc.
stats: Multichannel aware `stat'​

Miscellaneous effects
ladspa: Apply LADSPA plug-in effects e.g. CMT (Computer Music Toolkit)
synth: Synthesise/modulate audio tones or noise signals
newfile: Create a new output file when an effects chain ends.
restart: Restart 1st effects chain when multiple chains exist.​

Low-level signal processing effects
biquad: 2nd-order IIR filter using externally provided coefficients
downsample: Reduce sample rate by discarding samples
fir: FFT convolution FIR filter using externally provided coefficients
upsample: Increase sample rate by zero stuffing​

+ Experimental or incomplete effect; may change in future.

Multiple audio files can be combined (and then further processed with effects) using any one of the following combiner methods:
concatenate
mix
merge: E.g. two mono files to one stereo file
sequence: For playing multiple audio files/streams​
SoX - Sound eXchange | Features
 
Sist redigert:

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
I mp3-mirror.sh benyttes SoX for å downmixe surround-filer til stereofiler egnet for mp3, samt downsampling av high res til 16bit 44.1kHz. Begge nyttige bruksområder.
 

Falcon1i

Hi-Fi freak
Ble medlem
11.09.2012
Innlegg
1.822
Antall liker
1.823
Sted
Exil i huvudstaden
CMD/Windows är ju ganska begränsad avseende funktionalitet/scripting, jämfört med vad man göra i Linux.

Gow (Gnu On Windows) är ett smidigt program som ger tillgång till de flesta kommandon från Linux-världen
direkt via cmd i Windows, grep, awk, sed, gfind(find finns ju redan i win), tr ... Kan även köra bash-script.

https://github.com/bmatzelle/gow/wiki
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
cmd kan nok anses så godt som dødt i dag. Fra Windows 7 / Server 2008 og senere har alt dreid seg om PowerShell i Windows-scripting verdenen og Microsoft fronter dette sterkere og sterkere ved å til og med innføre rene kommandolinjedrevne servere (Windows Server Core)
 

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Etter en oppdatering av NAS firmware (RAIDiator 4.2.23) ble Apple Filing Protocol slått på som default og nå har jeg skjulte mapper som heter .AppleDouble overalt. Enda verre, inni noen av de mappene ligger det filer med extension .flac, men som bare er noen få bytes. Det roter til ting, og de mappene skal bort. Jeg har slått av AFP igjen slik at de ikke kommer tilbake. Er det noen som har et ferdig cmd-script for å slette alle .AppleDouble-mappene fra et filsystem?

Eventuelt blir dette dråpen for å installere terminal-interface på NAS'en, slik at jeg kan bruke shell-kommandoer direkte der.
 
N

nb

Guest
Etter en oppdatering av NAS firmware (RAIDiator 4.2.23) ble Apple Filing Protocol slått på som default og nå har jeg skjulte mapper som heter .AppleDouble overalt. Enda verre, inni noen av de mappene ligger det filer med extension .flac, men som bare er noen få bytes. Det roter til ting, og de mappene skal bort. Jeg har slått av AFP igjen slik at de ikke kommer tilbake. Er det noen som har et ferdig cmd-script for å slette alle .AppleDouble-mappene fra et filsystem?

Eventuelt blir dette dråpen for å installere terminal-interface på NAS'en, slik at jeg kan bruke shell-kommandoer direkte der.
I PowerShell burde noe ala dette funke:

get-childitem X:\music\ -include .AppleDouble -recurse | foreach ($_) {remove-item $_.fullname}


(men anbefaler å vente til Marsboer har kommet med et bedre forslag... scriptingen min er litt rusten.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Ikke cmd men jeg lagde et powershell-script til deg:

Lagre som f.eks "delete-folders.ps1"

Kode:
$foldername = ".AppleDouble"
$rootdir = "C:\Test"


Get-ChildItem -Path $rootdir -Include $foldername -Recurse -Force | Where-Object { $_.PSIsContainer } | Remove-Item -Recurse -Force
Kommandoen ser kun etter foldere ($_.PSIsContainer) og fjerner hidden files, som jeg antar at gjelder .AppleDouble. Slettingen skjer rekursivt, dvs at alt innhold i .AppleDouble-mappen slettes.

Kjør uten "Remove-Item"-delen først for å se at den plukker de riktige mappene.

Dersom du aldri har kjørt et powershell-script på maskinen din før så kan det hende at du får beskjed om at execution policy forhindrer deg i å kjøre scriptet.

Du kan tillate brukerinitiert kjøring av powershell-scripts med
Run -> powershell
Kode:
set-executionpolicy remotesigned
 
Sist redigert:

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Takk! Har installert Powershell, satt ExecutionPolicy til RemoteSigned (var det visst), og det ser ut som om versjonen uten Remove-Item funker. Den tar sin tid, men det ser ut som om det scriptet gjør jobben.

Har du et tips for hvor jeg kan finne enslags Dummies guide til å bruke EnableRootSSH direkte på NAS'en også?
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Ja, det stemmer det med remotesigned. Tok det på husken, noe som ikke alltid er like enkelt med powershell syntaksen.

Jeg har ingen erfaringer med RAIDiator og enabling av SSH, og jeg antar at dine google-skills er omtrent like effektive som mine :)
 

Asbjørn

Æresmedlem
Ble medlem
26.03.2006
Innlegg
27.151
Antall liker
17.108
Sted
Vingulmǫrk
Torget vurderinger
2
Det funket som en drøm. Alle .AppleDouble-mappene er sporløst borte.

Jeg har ikke brukt Powershell tidligere. Førsteinntrykket er at det er omtrent like lite selvforklarende som CMD, Visual Basic eller alt annet fra Microsoft. Eleganse og logisk konsistens synes ikke å være et viktig kriterie der borte i Redmond.
 
N

nb

Guest
I PowerShell får du også tilgang til kommandoen "robocopy" som står for "Robust Copy". Tenk om de bare hadde laget den opprinnelige kopieringsfunksjonen robust istedenfor.... Robocopy anbefales for øvrig til kopiering av store mengder filer, kopiering over nettverk og lignende aktiviteter.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Robocopy er et eksternt MS-program, så det er tilgjengelig selv om man ikke har powershell. Det kom imidlertid ikke som standard med Windows før Vista.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Når vi først har begynt å rote med powershell så kan jeg jo også legge ut et simpelt powershell-script for å mappe opp nettverksdrev, men i tillegg til dette også gi dem et skikkelig navn i stedet for default navnet som man får med net use.

Lagre scriptet som f.eks c:\scripts\map-network-drives.ps1

Kode:
# Map network shares that all users should have, and rename the drives to a prettier name
(New-Object -ComObject WScript.Network).MapNetworkDrive("Z:", "\\merkur\Common")
(New-Object -ComObject Shell.Application).NameSpace("Z:\").Self.Name = "Common"


(New-Object -ComObject WScript.Network).MapNetworkDrive("M:", "\\merkur\Media")
(New-Object -ComObject Shell.Application).NameSpace("M:\").Self.Name = "Media"
For å gjøre dette ekstra smooth og automatisk fungerende for alle brukere på maskinen så kan man legge til scriptet som et automatisk logon script, akkurat som i AD group policy, men i dette tilfellet kun for den lokale maskinen (jeg antar at de fleste av dere ikke kjører Active Directory domener på hjemmefronten).

run -> gpedit.msc

Når Local Group Policy Editor åpnes gjør du følgende:
- User Configuration -> Windows Settings -> Scripts (Logon/Logoff) -> Logon
- Velg "PowerShell Scripts" -> Add og bla deg frem til scriptet ditt.
- Trykk OK og lukk gpedit.
- Logg ut og inn for å verifisere (fjern eventuelle nettverksdrev du allerede har mountet på de gjeldende stasjonsbokstavene)

Feilsøking:
"Execution Policy" gjelder også for logon-scripts som kun kjøres av lokal sikkerhetspolicy. Det er så vidt jeg mener å huske kun dersom scriptet kjøres via AD Group Policy at man ikke trenger å tenke på dette.
 

marsboer

Hi-Fi freak
Ble medlem
04.04.2010
Innlegg
4.229
Antall liker
1.422
Sted
Phobos
Jeg har en utvidet variant av scriptet som mapper opp ulike drev basert på hvilken bruker som logger inn. Jeg vet ikke om dette er av interesse, men spør om det er aktuelt.
 
Topp Bunn