Script: Maak afspeellijst

Alles over programmeren in Linux
Gebruikersavatar
Mogenblue
Senior
Senior
Berichten: 135
Lid geworden op: Wo 18 Okt 2017, 08:27
Locatie: Amsterdam

Script: Maak afspeellijst

Berichtdoor Mogenblue » Di 23 Mar 2021, 14:57

Het is vrij eenvoudig om een afspeellijst aan te maken. In bestandsbeheer selecteer je de bestanden die je in een afspeellijst wil opnemen, in het contextmenu klik je op kopiëren en dan maak je een leeg document aan en plakt de bestanden daar in.
Je krijgt dan per regel een bestand met het volledige pad. Meer heb je voor een eenvoudige lijst niet nodig, maar het zou wel fijn zijn als je ook de speelduur van elk nummer erbij zou kunnen krijgen.

Met dit script geef je een map aan waar de mediabestanden te vinden zijn en eventueel ook een map waar je de afspeellijsten wil hebben. Als je daarna het script laat uitvoeren heb je in een paar tellen een mooie afspeellijst. Het is minder werk en je hebt meer informatie in de lijst.
Er zijn ook nog een paar opties om de uitvoer iets meer te sturen. Die staan bovenaan in het script.

Het tweede script in deze post verzorgt de integratie met Nemo. Dit script moet je in de scripts map van nemo plaatsen en dan kun je het script via het contextmenu aanroepen. Het voordeel daarvan is dat je ook selectief de bestanden kunt aangeven die in de afspeellijst moeten komen.

Het had allemaal natuurlijk in één script kunnen worden gezet, maar omdat je nog wel eens iets aan de settings wil veranderen is het handiger als het verwerkende script op een meer bereikbare plek staat dan in een verborgen map onder .local. Door de splitsing kun je het in je gewone scripts map zetten.

Het verwerkende script heet verwerk-afspeellijst.sh en dit staat er in:

Code: Selecteer alles

#!/bin/bash


# initialisatie

MediaMap='/home/mogenblue/Muziek/moderne albums/oriental'
AfspeellijstMap='/home/mogenblue/Scripts'
SetAfspeellijstInMediaMap=0
VoegMediaMapToeAanBestand=1

PrefixLijstNaam='Afspeellijst'
SuffixLijstNaam='m3u'

PrintEXTINF=1
Banner='Automatisch gegenereerde afspeellijst'

VerwijderAfspeellijstenUitNieuweLijst=1
PrintTotaalTijd=1
TextTotaleSpeelduur='Totale speelduur is '


#-------------------------------------------------------------------------------------------------------------

echo .
echo .
echo .
echo .

# set array empty when no matches found
shopt -s nullglob

# set huidige map voor afspeellijstmap als geen pad in ingevuld
if [[ $AfspeellijstMap == '' ]]
then
AfspeellijstMap=$(pwd)
fi


# als parent script niet bestaat ga dan naar de mediamap en lees alle bestanden in
if [ -z ${FileTotal+x} ]
then
cd "${MediaMap}"
# lees bestanden in array
ImageFileList=(*)
else
MediaMap=$(pwd)
fi


# pas het pad voor de afspeellijst aan
if [ $SetAfspeellijstInMediaMap -eq 1 ]
then
AfspeellijstMap="${MediaMap}"
fi
TekstDatumTijd=$(date +"%y%m%d-%H%M%S")
Afspeellijst=$(echo "${AfspeellijstMap}/${PrefixLijstNaam}-${TekstDatumTijd}.${SuffixLijstNaam}")

echo "Pad en naam van de afspeellijst wordt:"
echo "${Afspeellijst}"


# verwijder directories uit array
for InputFile in "${ImageFileList[@]}"
do
if [ -d "$InputFile" ]
then
# verwijder element uit array
mapfile -d $'\0' -t ImageFileList < <(printf '%s\0' "${ImageFileList[@]}" | grep -Pzv "$InputFile")
fi
done

# verwijder afspeellijsten uit array
for InputFile in "${ImageFileList[@]}"
do
if [ $VerwijderAfspeellijstenUitNieuweLijst -eq 0 ]
then
break
fi
# strip naam van bestand
InputFileExt="${InputFile##*.}"
if [ $InputFileExt == $SuffixLijstNaam ]
then
echo "$InputFile wordt verwijderd."
# verwijder element uit array
mapfile -d $'\0' -t ImageFileList < <(printf '%s\0' "${ImageFileList[@]}" | grep -Pzv "$InputFile")
fi
done


# schrijf header naar afspeellijst
if [ $PrintEXTINF -eq 1 ]
then
echo "#EXTM3U" > "$Afspeellijst"
echo "# $Banner" >> "$Afspeellijst"
fi


# lees aantal mediabestanden
FileTotal=${#ImageFileList[@]}
echo .
echo "${FileTotal} mediabestanden gevonden:"


# mediamap aanpassen
MediaMap="${MediaMap}/"
if [ $VoegMediaMapToeAanBestand -eq 0 ]
then
MediaMap=""
fi


# invoer bestanden verwerken
FileCount=1
TotalTime=0
for InputFile in "${ImageFileList[@]}"
do

# strip extensie van bestand
InputFileName="${InputFile%.*}"
# strip naam van bestand
InputFileExt="${InputFile##*.}"

# lees duur van het mediabestand
if [ $InputFileExt == $SuffixLijstNaam ]
then
# afspeellijst prefix toevoegen aan naam afspeellijst
InputFileName="$PrefixLijstNaam $InputFileName"
# duur van afspeellijst wordt niet meegeteld
Tijd=0
else
# lees duur van het bestand
Tijd=$(ffprobe -i "${InputFile}" -show_entries format=duration -v quiet -of csv="p=0")
fi

# duur afronden op 3 decimalen
Tijd3Decimalen=$(echo "scale=3; ${Tijd} / 1" | bc)
# duur afronden op 0 decimalen
TijdAfgerond=$(echo "scale=0; ${Tijd} / 1" | bc)
# format tijd
TijdOpmaak=$(printf '%02dh:%02dm:%02ds' $((TijdAfgerond/3600)) $((TijdAfgerond%3600/60)) $((TijdAfgerond%60)))

echo "$FileCount - duur: $TijdOpmaak, $InputFileName"

# schrijf naar afspeellijst
if [ $PrintEXTINF -eq 1 ]
then
echo "" >> "$Afspeellijst"
echo "#EXTINF:${Tijd3Decimalen},${InputFileName}" >> "$Afspeellijst"
fi
#echo "${MediaMap}/${InputFile}" >> "$Afspeellijst"
echo "${MediaMap}${InputFile}" >> "$Afspeellijst"

let TotalTime=TotalTime+TijdAfgerond
(( FileCount++ ))
done


# totaaltijd opmaken
TijdAfgerond=$(echo "scale=0; ${TotalTime} / 1" | bc)
TijdOpmaak=$(printf '%02dh:%02dm:%02ds' $((TijdAfgerond/3600)) $((TijdAfgerond%3600/60)) $((TijdAfgerond%60)))
echo .
echo "${TextTotaleSpeelduur}$TijdOpmaak."

# totaaltijd afdrukken
if [ $PrintTotaalTijd -eq 1 ]
then
echo "" >> "$Afspeellijst"
echo "#--------------------------------------------------------------------------------------------------" >> "$Afspeellijst"
echo "# ${TextTotaleSpeelduur}$TijdOpmaak." >> "$Afspeellijst"
fi


echo .
echo "Alle bestanden zijn verwerkt."

In het oorspronkelijke script wordt veel gebruik gemaak van inspringen om de leesbaarheid te verhogen. Dat valt op dit forum weg omdat html een reeks spaties afkapt tot 1. Tabs worden bijvoorbeeld gebruikt in if-then structuren en for-next loops.

Met de optie VerwijderAfspeellijstenUitNieuweLijst kun je aangeven of bestaande afspeellijsten in de media map wel of niet in de nieuwe lijst moeten worden opgenomen. Er worden dus geen lijsten van de schijf gewist, ze worden alleen wel of niet in de nieuwe lijst opgenomen.

Dan nog het script voor de integratie met Nemo. Dit heet maak-afspeellijst.sh.

Code: Selecteer alles


#!/bin/bash

# zet invoer bestanden in array
ImageFileList=( "$@" )

# lees aantal invoerbestanden
FileTotal=( "$#" )


# script voor verwerking inlezen
source '/home/mogenblue/Scripts/verwerk-afspeellijst.sh'

Dat is dus een zeer simpel script. Het leest alleen de geselecteerde bestanden in vervolgens wordt het verwerkende script ingelezen voor de verdere uitvoering.

Overigens moeten beide scripts gewoon uitvoerbaar zijn. En de precieze locatie voor het tweede script is
/home/mogenblue/.local/share/nemo/scripts/maak-afspeellijst.sh
waarbij aangetekend wordt dat mogenblue door je eigen username dient te worden vervangen.

Als je veel scripts in het contextmenu gaat opnemen kun je ook submappen maken en dan krijg je automatisch die mapstructuur in je contextmenu terug te zien.


Ik ga ook eens kijken naar het combineren van afspeellijsten.
Gebruikersavatar
Mogenblue
Senior
Senior
Berichten: 135
Lid geworden op: Wo 18 Okt 2017, 08:27
Locatie: Amsterdam

Re: Script: Maak afspeellijst

Berichtdoor Mogenblue » Ma 29 Mar 2021, 15:33


In het oorspronkelijke script wordt veel gebruik gemaak van inspringen om de leesbaarheid te verhogen. Dat valt op dit forum weg omdat html een reeks spaties afkapt tot 1. Tabs worden bijvoorbeeld gebruikt in if-then structuren en for-next loops.

Hier is een voorbeeld van het script met tabs zoals het er uit hoort te zien.


Afbeelding
Gebruikersavatar
Mogenblue
Senior
Senior
Berichten: 135
Lid geworden op: Wo 18 Okt 2017, 08:27
Locatie: Amsterdam

Re: Script: Maak afspeellijst

Berichtdoor Mogenblue » Vr 18 Jun 2021, 11:49

Als je liever de naam van de map wil gebruiken voor de afspeellijst ipv datum en tijd kun je het volgende doen.

#TekstDatumTijd=$(date +"%y%m%d-%H%M%S")
#Afspeellijst=$(echo "${AfspeellijstMap}/${PrefixLijstNaam}-${TekstDatumTijd}.${SuffixLijstNaam}")

FolderNaam=$(basename "$MediaMap")
Afspeellijst=$(echo "${AfspeellijstMap}/${FolderNaam}.${SuffixLijstNaam}")



Referentie:
Extract filename and extension in Bash

Terug naar “Programmeren”

Wie is er online

Gebruikers op dit forum: Google [Bot] en 2 gasten