Python Library Media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

convert.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import io
  2. from media import common
  3. from PIL import Image
  4. import subprocess
  5. import platform
  6. import logging
  7. import os
  8. import subprocess
  9. try:
  10. from config import APP_NAME as ROOT_LOGGER_NAME
  11. except ImportError:
  12. ROOT_LOGGER_NAME = 'root'
  13. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  14. def get_pil_image(media_instance):
  15. try:
  16. media_instance = media_instance._im
  17. except AttributeError:
  18. pass
  19. #
  20. if type(media_instance) == str:
  21. ft = common.get_filetype(media_instance)
  22. if ft == common.FILETYPE_IMAGE:
  23. return Image.open(media_instance)
  24. elif ft == common.FILETYPE_VIDEO:
  25. if platform.system() == 'Linux':
  26. cmd = 'ffmpeg -ss 0.5 -i "' + media_instance + '" -vframes 1 -f image2pipe pipe:1 2> /dev/null'
  27. else:
  28. cmd = 'ffmpeg -ss 0.5 -i "' + media_instance + '" -vframes 1 -f image2pipe pipe:1 2> NULL'
  29. try:
  30. data = subprocess.check_output(cmd, shell=True)
  31. except subprocess.CalledProcessError:
  32. logger.warning('ffmpeg seems to be not installed')
  33. return None
  34. ffmpeg_handle = io.BytesIO(data)
  35. im = Image.open(ffmpeg_handle)
  36. return im.copy()
  37. logger.warning('Filetype is not supported (%s)', media_instance)
  38. elif type(media_instance) == Image.Image:
  39. return media_instance.copy()
  40. else:
  41. logger.warning('Instance type is not supported: %s' % type(media_instance))
  42. def FilenameFilter(filename: str) -> str:
  43. # WHITELIST = [os.path.sep, os.path.extsep]
  44. WHITELIST = [chr(x) for x in range(ord('0'), ord('9') + 1)]
  45. WHITELIST += [chr(x) for x in range(ord('a'), ord('z') + 1)]
  46. WHITELIST += ["ä", "ö", "ü", "ß"]
  47. #
  48. rv = ""
  49. for c in filename.lower():
  50. rv += c if c in WHITELIST else '_'
  51. return rv
  52. def track_to_targetpath(basepath: str, track: dict, ext: str):
  53. return os.path.join(
  54. basepath,
  55. FilenameFilter(track[common.KEY_ARTIST]),
  56. "%04d_" % track[common.KEY_YEAR] + FilenameFilter(track[common.KEY_ALBUM]),
  57. "%02d_" % track[common.KEY_TRACK] + FilenameFilter(track[common.KEY_TITLE]) + "." + ext
  58. )
  59. def disc_track_rip(track_num: int, target_file: str, progress_callback):
  60. FAC_SEC_VAL = 1224
  61. #
  62. cdp_cmd = subprocess.getoutput("which cdparanoia")
  63. if not cdp_cmd:
  64. logger.error("cdparanoia is required for ripping. You need to install it to your system.")
  65. else:
  66. cmd = [cdp_cmd, "-e", "-X", "%d" % track_num, target_file]
  67. cdp = subprocess.Popen(cmd, text=True, stderr=subprocess.PIPE)
  68. #
  69. rval = 0
  70. min_sec = None
  71. max_sec = None
  72. min_read = None
  73. while (out := cdp.stderr.readline()) != "":
  74. out = out.strip()
  75. # identify minimum sector
  76. if ("Ripping from sector" in out):
  77. min_sec = int(list(filter(None, out.split(" ")))[3])
  78. # identify maximum sector
  79. if ("to sector" in out):
  80. max_sec = int(list(filter(None, out.split(" ")))[2])
  81. # identify progress
  82. if "[read]" in out:
  83. val = int(out.split(" ")[-1])
  84. if not min_read:
  85. min_read = val
  86. rval = max(val, rval)
  87. try:
  88. dsec = max_sec - min_sec
  89. except TypeError:
  90. logger.exception("Error while parsing cdparanoia. Start and End sector could not be detrmined.")
  91. else:
  92. p = (rval - min_read) / FAC_SEC_VAL / dsec
  93. p = min(p, 1)
  94. progress_callback(p)
  95. progress_callback(1)
  96. return cdp.wait()
  97. def wav_to_mp3(infile: str, basepath: str, track_information, progress_callback, bitrate=256, vbr=0, quaulity=0):
  98. lame_parameter = {
  99. common.KEY_ARTIST: '--ta',
  100. common.KEY_ALBUM: '--tl',
  101. common.KEY_YEAR: '--ty',
  102. common.KEY_GENRE: '--tg',
  103. common.KEY_TRACK: '--tn',
  104. common.KEY_TITLE: '--tt'
  105. }
  106. lame_cmd = subprocess.getoutput("which lame")
  107. if not lame_cmd:
  108. logger.error("lame is required for encoding. You need to install it to your system.")
  109. else:
  110. outfile = track_to_targetpath(basepath, track_information, 'mp3')
  111. cmd = [lame_cmd, "-b", str(bitrate), "-V", str(vbr), "--vbr-old", "-q", str(quaulity), infile, outfile]
  112. cmd.extend(["--tc", "Encoded by lame"])
  113. for key in track_information:
  114. cmd.extend([lame_parameter[key], str(track_information[key])])
  115. lame = subprocess.Popen(cmd, text=True, stderr=subprocess.PIPE)
  116. while (out := lame.stderr.readline()) != "":
  117. out = out.strip()
  118. posb = out.find("(")
  119. posp = out.find("%")
  120. if posb >= 0 and posp >= 0:
  121. p = int(out[posb+1:posp]) / 100
  122. progress_callback(p)
  123. progress_callback(1)
  124. return lame.wait()