vid_utils.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import os
  2. from glob import glob, escape
  3. from subprocess import Popen, PIPE
  4. from contextlib import contextmanager
  5. from telegram import InlineKeyboardButton
  6. from db import VidDatabase
  7. class BadLink(Exception):
  8. pass
  9. class Video:
  10. def __init__(self, link=None, vid=None, init_keyboard=False):
  11. self.db = VidDatabase(os.path.join(os.environ['CONF_FOLDER'], "viddb.sqlite3"))
  12. if not self.db.is_valid:
  13. # Database file not present
  14. # Create a new database
  15. self.db.create()
  16. if vid is None and link is not None:
  17. self.link = link
  18. self.file_name = None
  19. elif vid is not None and link is None:
  20. self.link, self.code = self.db.select_vid(vid)
  21. else:
  22. raise Exception('what is going on?')
  23. if init_keyboard:
  24. self.formats = self.get_formats()
  25. self.keyboard = self.generate_keyboard()
  26. def get_formats(self):
  27. formats = {}
  28. p = Popen(["youtube-dl", "-F", self.link], stdout=PIPE, stderr=PIPE).communicate()
  29. it = iter(str(p[0], 'utf-8').split('\n')) # iterator of output lines
  30. try:
  31. while "code extension" not in next(it):
  32. pass # Remove garbage lines
  33. except StopIteration:
  34. raise BadLink("youtube-dl couldn't download the link you provided") # Isn't a valid youtube link
  35. while True:
  36. try:
  37. line = next(it)
  38. if not line:
  39. raise StopIteration # Usually the last line is empty
  40. if "video only" in line:
  41. continue # I don't need video without audio
  42. except StopIteration:
  43. break
  44. else:
  45. format_code, extension, resolution, *_ = line.strip().split()
  46. key = '{},{}'.format(extension, resolution)
  47. index = self.db.insert_vid(self.link, format_code)
  48. formats[key] = index
  49. return formats
  50. def generate_keyboard(self):
  51. """ Generate a list of InlineKeyboardButton of resolutions """
  52. kb = []
  53. for key in self.formats.keys():
  54. cb = "{}".format(self.formats[key])
  55. kb.append([InlineKeyboardButton(key, callback_data=cb)])
  56. return kb
  57. def download(self):
  58. p = Popen(["youtube-dl", "-f", self.code, self.link], stdout=PIPE, stderr=PIPE).communicate()
  59. for line in str(p[0], 'utf-8').split('\n'):
  60. if "[download] Destination:" in line:
  61. self.file_name = line[24:] # name of the file
  62. def check_dimension(self):
  63. if os.path.getsize(self.file_name) > 50 * 1024 * 1023:
  64. Popen(["split", "-b", "49M", self.file_name, self.file_name])
  65. os.remove(self.file_name)
  66. return glob(escape(self.file_name) + '*')
  67. @contextmanager
  68. def send(self):
  69. files = self.check_dimension() # split if size >= 50MB
  70. yield files
  71. for f in files: # removing old files
  72. os.remove(f)
  73. #__________________________OLD STUFFS, TOUCH CAREFULLY__________________________
  74. # this is the soft-split version, require avconv, but the audio isn't synchronized, avconv's problems :(
  75. '''
  76. def get_duration(filepath): # get duration in seconds
  77. cmd = "avconv -i %s" % filepath
  78. p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
  79. di = p.communicate()
  80. for line in di:
  81. if line.rfind(b"Duration") > 0:
  82. duration = str(re.findall(b"Duration: (\d+:\d+:[\d.]+)", line)[0])
  83. return 3600 * int(duration[2: 4]) + 60 * int(duration[5: 7]) + int(duration[8: 10])
  84. def check_dimension(f): # if f is bigger than 50MB split it in subvideos
  85. if os.path.getsize(f) > 50 * 1024 * 1023:
  86. duration = get_duration(f)
  87. for i in range(0, duration, 180):
  88. start = strftime("%H:%M:%S", strptime('{0} {1} {2}'.format(i // 3600, (i // 60) % 60, i % 60), "%H %M %S")) # TODO this is not pythonic code!
  89. os.system("""avconv -i '{0}' -vcodec copy -acodec copy -ss {1} -t {2} 'part_{3}.mp4'""".format(f, start, 180, (i // 180) % 180))
  90. os.remove(f) # delete original file
  91. '''