vid_utils.py 3.8 KB

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