Advertisement
julian_hughes

bashplaylist - extm3u playlist maker

May 22nd, 2012
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 2.98 KB | None | 0 0
  1. #!/bin/bash
  2. #Dependencies: usual gnu utils, ffmpeg or ffprobe
  3.  
  4. ##june 07 2012 edited to remove unwanted \ in regex expression which ###prevented ogg files from being parsed.
  5.  
  6. function usage ()
  7. {
  8.     printf "\nUSAGE:
  9. \t$(basename "$0") [options] {-o out} <directory>\n
  10. OPTIONS:
  11. \t-p  writes the file names in .m3u with full path\n\
  12. \t    (default is simple file name without path)\n
  13. \t-r  recurses through subdirectories and writes file names with
  14. \t    full path\n
  15. \t-o <output directory>  (default is target directory)\n
  16. \t$(basename "$0") finds the audio files in the directory, parses
  17. \tthe metadata, then writes an extended .m3u playlist\n
  18. \t$(basename "$0") understands the same files as  your
  19. \tinstalled version of ffmpeg.\n
  20. \tIf $(basename "$0") fails please check output directory exists
  21. \tand is writeable.\n\n"
  22. }
  23.  
  24. #dump file data;grep metadata relevant to extm3u.
  25. #extm3u spec states that stated time MUST be equal to or greater than
  26. #track duration so all times are rounded UP to integer i.e. 38.00 secs
  27. #becomes 38 seconds but 38.10 secs or 38.95 seconds become 39 seconds.
  28. function getdata ()
  29. {
  30. ffprobe -show_format "$f">"$DATA"
  31.  
  32. PERF=$(grep -m 1 -i tag:artist "$DATA" |\
  33. awk -F "=" '{$1="";$0=substr($0,2)}1' |cleantag)
  34. TIT=$(grep -m 1 -i tag:title "$DATA" |\
  35. awk -F "=" '{$1="";$0=substr($0,2)}1' |cleantag)
  36. SEC=$(printf %.2f\\n $(grep -m 1 -i -e "^duration" "$DATA" |\
  37. awk -F "=" '{print $2}'))
  38. SEC=$(printf %0.f\\n $(echo "$SEC+0.5"|bc))
  39. }
  40.  
  41. #remove problematic characters from metadata.
  42. function cleantag ()
  43. {
  44.     sed 's/[;]/-/g;s/[/]/-/g;s/[<]/-/g;s/[>]/-/g;s/[:]/-/g;s/[|]/-/g'
  45. }
  46.  
  47. #user options
  48. while getopts 'o:pr' OPTION
  49. do
  50.     case $OPTION in
  51.     o)  oflag=1
  52.         oval=$OPTARG
  53.         ;;
  54.     p)  pflag=1
  55.         ;;
  56.     r)  rflag=1
  57.         pflag=1
  58.         ;;
  59.     esac
  60. done
  61. shift $(($OPTIND-1))
  62.  
  63. if [ $# -lt 1 ]; then
  64.     usage
  65.     exit 1
  66. fi
  67.  
  68. #recurse?
  69. if [ $rflag ]; then
  70.     DEPTH=''
  71.     else
  72.     DEPTH="-maxdepth 1"
  73. fi
  74.  
  75. for i in "$@" ; do
  76. #ensure .m3u name is not dot file if script run within target directory.
  77. PN=$(basename "$(readlink -f "$i")").m3u
  78.  
  79. #some simple error checking
  80. if [ ! -d "$i" ]; then
  81.     usage
  82.     exit
  83. fi
  84.  
  85. #set output destination. Output dir exists and writeable?
  86. if [ $oflag ]; then
  87.     if [ ! -d "$oval" -o ! -w "$oval" ]; then
  88.     usage
  89.     exit
  90.     fi
  91.     PL=$oval/"$PN"
  92.     else
  93.     PL="$i"/"$PN"
  94. fi
  95.  
  96. #create/overwrite .m3u and write extm3u's generic 1st line
  97. printf "#EXTM3U">"$PL"
  98.  
  99. #find all audio files to be referenced in .m3u
  100. find "$i" $DEPTH -iregex ".*\(flac\|ape\|wv\|wav\|mpc\|aac\|m4a\|wma\|\
  101. mp3\|ogg\|oga\|mka\|ac3\)$" |sort |while read f ; do
  102.  
  103. #use full path or simple names?
  104. if [ $pflag ]; then
  105.     FILENAME=$(readlink -f "$f")
  106.     else
  107.     FILENAME="${f##*/}"
  108. fi
  109.  
  110. #where to dump ffprobe's file info
  111. DATA="${f%.*}"_data
  112.  
  113. #run getdata silently (ffprobe generates much unwanted text)
  114. getdata>/dev/null 2>&1
  115.  
  116. #write to the playlist, clean up.
  117. printf "\n#EXTINF:$SEC,$PERF - $TIT\n$FILENAME">>"$PL"
  118. rm "$DATA"
  119. done
  120.  
  121. #confirm to user, quit.
  122. echo "Wrote "$PL""
  123. done
  124. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement