Advertisement
julian_hughes

Untitled

Mar 20th, 2013
2,060
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/bash
  2. #Dependencies: ffmpeg or ffprobe, standard gnu utils (including bc)
  3. #
  4. #april 21 2014 edited to also work with locales that
  5. #use , instead of .for decimal position (thanks to Tina Keil).
  6. #march 20 2013 edited to accommodate opus files and to fix error in fetching
  7. #durations, caused by changes in ffprobe.
  8. #june 07 2012 edited to remove unwanted \ in regex expression which
  9. #prevented ogg files from being parsed.
  10. #december 22 2015 edited to add support for relative paths, thanks to Dave.
  11. # january 9 2016 removed problemaatic relative paths function.
  12.  
  13. #also work with locales that use , instead of .for decimal position.
  14. LC_NUMERIC=C LC_COLLATE=C
  15.  
  16. function usage ()
  17. {
  18.     printf "\nUSAGE:
  19. \t$(basename "$0") [options] {-o out} <directory>\n
  20. OPTIONS:
  21. \t-D  Don't overwrite existing playlist (default is to replace)\n
  22. \t-s  Simple m3u8 playlist instead of extended m3u8\n
  23. \t-p  writes the file names in .m3u with full path\n\
  24. \t    (default is simple file name without path)\n
  25. \t-d  Set the recursion depth (default is 1)\n
  26. \t-r  Recurses through subdirectories and writes file names with
  27. \t    full path\n
  28. \t-c  Format playlist for Sansa Clip+ Internal Memory (implies -p)
  29. \t
  30. \t-C  Format playlist for Sansa Clip+ MicroSDHC (implies -p)
  31. \t
  32. \t-H  Format playlist for iriver H10/100/300 series players (implies -p)
  33. \t    You MUST change the MicroSDHC card label and mount point in
  34. \t    the sed expressions to the ACTUAL MicroSDHC card label and
  35. \t    mount point on your OS.  The Clip internal storage and iRiver H
  36. \t    values are quite generic but Clip external storage values could be
  37. \t    anything - user must check this.\n
  38. \t-o <output directory>  (default is target directory)\n
  39. \t$(basename "$0") finds the audio files in the directory, parses
  40. \tthe metadata, then writes an extended .m3u playlist\n
  41. \t$(basename "$0") understands the same files as  your
  42. \tinstalled version of ffmpeg.\n
  43. \tIf $(basename "$0") fails please check output directory exists
  44. \tand is writeable.\n\n"
  45. }
  46.  
  47. #dump file data;grep metadata relevant to extm3u.
  48. #extm3u spec states that stated time MUST be equal to or greater than
  49. #track duration so all times are rounded UP to integer i.e. 38.00 secs
  50. #becomes 38 seconds but 38.10 secs or 38.95 seconds become 39 seconds.
  51. function getdata ()
  52. {
  53. ffprobe -v quiet -show_format -show_streams "$f">"$DATA"
  54.  
  55. PERF=$(grep -m 1 -i tag:artist "$DATA" |\
  56. awk -F "=" '{$1="";$0=substr($0,2)}1' |cleantag)
  57. TIT=$(grep -m 1 -i tag:title "$DATA" |\
  58. awk -F "=" '{$1="";$0=substr($0,2)}1' |cleantag)
  59. SEC=$(printf %.2f\\n $(grep -m 1 -i -e "^duration=" "$DATA" |\
  60. awk -F "=" '{print $2}'))
  61. SEC=$(printf %0.f\\n $(echo "$SEC+0.5"|bc))
  62. }
  63.  
  64. #remove problematic characters from metadata.
  65. function cleantag ()
  66. {
  67.     sed 's/[;]/-/g;s/[/]/-/g;s/[<]/-/g;s/[>]/-/g;s/[:]/-/g;s/[|]/-/g'
  68. }
  69.  
  70. #user options
  71. while getopts 'CcDHo:prs' OPTION
  72. do
  73.     case $OPTION in
  74.     o)  oflag=1
  75.         oval=$OPTARG
  76.         ;;
  77.     p)  pflag=1
  78.         ;;
  79.     r)  rflag=1
  80.         pflag=1
  81.         ;;
  82.     R)  rflag=1
  83.         relpathflag=1
  84.         ;;
  85.     c)  cflag=1
  86.         ;;
  87.     C)  Cflag=1
  88.         pflag=1
  89.         ;;
  90.     H)  Hflag=1
  91.         pflag=1
  92.         ;;
  93.     s)  sflag=1
  94.         ;;
  95.     D)  Dflag=1
  96.         ;;
  97.     esac
  98. done
  99. shift $(($OPTIND-1))
  100.  
  101. if [ $# -lt 1 ]; then
  102.     usage
  103.     exit 1
  104. fi
  105.  
  106. #recurse?
  107. if [ $rflag ]; then
  108.     DEPTH=''
  109. else
  110.     DEPTH="-maxdepth 1"
  111. fi
  112.  
  113. for i in "$@" ; do
  114. #ensure .m3u name is not dot file if script run within target directory.
  115. PN=$(basename "$(readlink -f "$i")").m3u
  116.  
  117. #some simple error checking
  118. if [ ! -d "$i" ]; then
  119.     usage
  120.     exit
  121. fi
  122.  
  123. #set output destination. Output dir exists and writeable?
  124. if [ $oflag ]; then
  125.     if [ ! -d "$oval" -o ! -w "$oval" ]; then
  126.     usage
  127.     exit
  128.     fi
  129.     PL=$oval/"$PN"
  130.     else
  131.     PL="$i"/"$PN"
  132. fi
  133.  
  134. #playlist exists? overwrite?
  135. if [ $Dflag ] && [ -f "$PL" ]; then
  136.     printf "\n$PL already exists.\n"
  137.     continue
  138.     else
  139.     > "$PL"
  140. fi
  141.  
  142. if [ ! $sflag ]; then
  143.     #write mandatory extm3u8 header
  144.     printf "#EXTM3U">"$PL"
  145.     WRITE=xlist
  146.     else
  147.     WRITE=slist
  148. fi
  149.  
  150. #find all audio files to be referenced in .m3u
  151. find "$i" $DEPTH -iregex ".*\(flac\|ape\|wv\|wav\|mpc\|aac\|m4a\|wma\|\
  152. mp3\|ogg\|oga\|mka\|ac3\|opus\)$" |sort |while read f ; do
  153.  
  154. #use full path or simple names?
  155. if [ $pflag ]; then
  156.     if [ $cflag ]; then
  157.         FILENAME=$(readlink -f "$f"|sed 's/\/media\/SANSA\ CLIPP//')
  158.     elif [ $Cflag ]; then
  159.         FILENAME=$(readlink -f "$f"|sed 's/media\/LEX/\<microSD1\>/')
  160.     elif [ $Hflag ]; then
  161.         FILENAME=$(readlink -f "$f"|sed 's/media\/H[0-9]*.//')
  162.     else
  163.         FILENAME=$(readlink -f "$f")
  164.     fi
  165. elif [ $relpathflag ]; then
  166.     FILENAME=$(readlink -f "$f")
  167.     FILENAME=$(relpath $PWD $FILENAME)
  168. else
  169.     FILENAME="${f##*/}"
  170. fi
  171.  
  172. #where to dump ffprobe's file info
  173. DATA="${f%.*}"_data
  174.  
  175. #run getdata silently (ffprobe generates much unwanted text)
  176. getdata>/dev/null 2>&1
  177.  
  178. #write to the playlist, clean up.
  179. printf "\n#EXTINF:$SEC,$PERF - $TIT\n$FILENAME">>"$PL"
  180. rm "$DATA"
  181. done
  182.  
  183. #confirm to user, quit.
  184. echo "Wrote "$PL""
  185. done
  186. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement