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.

303 lines
10 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. #!/usr/bin/env python2
  2. """Youtubedlg module to parse the options.
  3. Note:
  4. If you want to add new values on the module attributes
  5. e.g. (SUBS_LANG, VIDEO_FORMATS, etc..) you also need to add the
  6. values on the optionsframe module in order for them to be
  7. visible from the GUI.
  8. """
  9. import os.path
  10. from .utils import remove_shortcuts
  11. SUBS_LANG = {
  12. "English": "en",
  13. "Greek": "gr",
  14. "Portuguese": "pt",
  15. "French": "fr",
  16. "Italian": "it",
  17. "Russian": "ru",
  18. "Spanish": "es",
  19. "German": "de"
  20. }
  21. VIDEO_FORMATS = {
  22. "default": "0",
  23. "none": "0",
  24. "3gp [176x144]": "17",
  25. "3gp [320x240]": "36",
  26. "flv [400x240]": "5",
  27. "flv [640x360]": "34",
  28. "flv [854x480]": "35",
  29. "webm [640x360]": "43",
  30. "webm [854x480]": "44",
  31. "webm [1280x720]": "45",
  32. "webm [1920x1080]": "46",
  33. "mp4 [640x360]": "18",
  34. "mp4 [1280x720]": "22",
  35. "mp4 [1920x1080]": "37",
  36. "mp4 [4096x3072]": "38",
  37. "mp4 144p (DASH)": "160",
  38. "mp4 240p (DASH)": "133",
  39. "mp4 360p (DASH)": "134",
  40. "mp4 480p (DASH)": "135",
  41. "mp4 720p (DASH)": "136",
  42. "mp4 1080p (DASH)": "137",
  43. "mp4 1440p (DASH)": "264",
  44. "mp4 2160p (DASH)": "138",
  45. "webm 240p (DASH)": "242",
  46. "webm 360p (DASH)": "243",
  47. "webm 480p (DASH)": "244",
  48. "webm 720p (DASH)": "247",
  49. "webm 1080p (DASH)": "248",
  50. "webm 1440p (DASH)": "271",
  51. "webm 2160p (DASH)": "272",
  52. "mp4 360p (3D)": "82",
  53. "mp4 480p (3D)": "83",
  54. "mp4 720p (3D)": "84",
  55. "mp4 1080p (3D)": "85",
  56. "webm 360p (3D)": "100",
  57. "webm 480p (3D)": "101",
  58. "webm 720p (3D)": "102",
  59. "m4a 48k (DASH AUDIO)": "139",
  60. "m4a 128k (DASH AUDIO)": "140",
  61. "m4a 256k (DASH AUDIO)": "141",
  62. "webm 48k (DASH AUDIO)": "171",
  63. "webm 256k (DASH AUDIO)": "172"
  64. }
  65. AUDIO_QUALITY = {
  66. "high": "0",
  67. "mid": "5",
  68. "low": "9"
  69. }
  70. FILESIZE_UNITS = {
  71. 'Bytes': '',
  72. 'Kilobytes': 'k',
  73. 'Megabytes': 'm',
  74. 'Gigabytes': 'g',
  75. 'Terabytes': 't',
  76. 'Petabytes': 'p',
  77. 'Exabytes': 'e',
  78. 'Zettabytes': 'z',
  79. 'Yottabytes': 'y'
  80. }
  81. class OptionHolder():
  82. """Simple data structure that holds informations for the given option.
  83. Args:
  84. name (string): Option name. Must be a valid option name
  85. from the optionsmanager.OptionsManager class.
  86. See optionsmanager.OptionsManager load_default() method.
  87. flag (string): The option command line switch.
  88. See https://github.com/rg3/youtube-dl/#options
  89. default_value (any): The option default value. Must be the same type
  90. with the corresponding option from the optionsmanager.OptionsManager
  91. class.
  92. requirements (list): The requirements for the given option. This
  93. argument is a list of strings with the name of all the options
  94. that this specific option needs. For example 'subs_lang' needs the
  95. 'write_subs' option to be enabled.
  96. """
  97. def __init__(self, name, flag, default_value, requirements=[]):
  98. self.name = name
  99. self.flag = flag
  100. self.requirements = requirements
  101. self.default_value = default_value
  102. def is_boolean(self):
  103. """Returns True if the option is a boolean switch else False. """
  104. return type(self.default_value) is bool
  105. def check_requirements(self, options_dict):
  106. """Check if the required options are enabled.
  107. Args:
  108. options_dict (dictionary): Dictionary with all the options.
  109. Returns:
  110. True if any of the required options is enabled else False.
  111. """
  112. if not self.requirements:
  113. return True
  114. return any(map(lambda x: options_dict[x], self.requirements))
  115. class OptionsParser():
  116. """Parse optionsmanager.OptionsManager options.
  117. This class is responsible for turning some of the youtube-dlg options
  118. to youtube-dl command line options.
  119. """
  120. def __init__(self):
  121. self._ydl_options = [
  122. OptionHolder('playlist_start', '--playlist-start', 1),
  123. OptionHolder('playlist_end', '--playlist-end', 0),
  124. OptionHolder('max_downloads', '--max-downloads', 0),
  125. OptionHolder('username', '-u', ''),
  126. OptionHolder('password', '-p', ''),
  127. OptionHolder('video_password', '--video-password', ''),
  128. OptionHolder('retries', '-R', 10),
  129. OptionHolder('proxy', '--proxy', ''),
  130. OptionHolder('user_agent', '--user-agent', ''),
  131. OptionHolder('referer', '--referer', ''),
  132. OptionHolder('ignore_errors', '-i', False),
  133. OptionHolder('write_description', '--write-description', False),
  134. OptionHolder('write_info', '--write-info-json', False),
  135. OptionHolder('write_thumbnail', '--write-thumbnail', False),
  136. OptionHolder('min_filesize', '--min-filesize', 0),
  137. OptionHolder('max_filesize', '--max-filesize', 0),
  138. OptionHolder('write_all_subs', '--all-subs', False),
  139. OptionHolder('write_auto_subs', '--write-auto-sub', False),
  140. OptionHolder('write_subs', '--write-sub', False),
  141. OptionHolder('keep_video', '-k', False),
  142. OptionHolder('restrict_filenames', '--restrict-filenames', False),
  143. OptionHolder('save_path', '-o', ''),
  144. OptionHolder('embed_subs', '--embed-subs', False, ['write_auto_subs', 'write_subs']),
  145. OptionHolder('to_audio', '-x', False),
  146. OptionHolder('audio_format', '--audio-format', '', ['to_audio']),
  147. OptionHolder('video_format', '-f', ''),
  148. OptionHolder('subs_lang', '--sub-lang', '', ['write_subs']),
  149. OptionHolder('audio_quality', '--audio-quality', '5', ['to_audio'])
  150. ]
  151. def parse(self, options_dictionary):
  152. """Parse optionsmanager.OptionsHandler options.
  153. Parses the given options to youtube-dl command line arguments.
  154. Args:
  155. options_dictionary (dictionary): Dictionary with all the options.
  156. Returns:
  157. List of strings with all the youtube-dl command line options.
  158. """
  159. options_list = ['--newline']
  160. # Create a copy of options_dictionary
  161. # We don't want to edit the original options dictionary
  162. # and change some of the options values like 'save_path' etc..
  163. options_dict = options_dictionary.copy()
  164. self._build_savepath(options_dict)
  165. self._build_subslang(options_dict)
  166. self._build_videoformat(options_dict)
  167. self._build_audioquality(options_dict)
  168. self._build_filesizes(options_dict)
  169. # Parse basic youtube-dl command line options
  170. for option in self._ydl_options:
  171. if option.check_requirements(options_dict):
  172. value = options_dict[option.name]
  173. if value != option.default_value:
  174. options_list.append(option.flag)
  175. if not option.is_boolean():
  176. options_list.append(str(value))
  177. # Parse cmd_args
  178. for option in options_dict['cmd_args'].split():
  179. options_list.append(option)
  180. return options_list
  181. def _build_savepath(self, options_dict):
  182. """Build the save path.
  183. We use this method to build the value of the 'save_path' option and
  184. store it back to the options dictionary.
  185. Args:
  186. options_dict (dictionary): Copy of the original options dictionary.
  187. """
  188. save_path = remove_shortcuts(options_dict['save_path'])
  189. if options_dict['output_format'] == 'id':
  190. save_path = os.path.join(save_path, '%(id)s.%(ext)s')
  191. elif options_dict['output_format'] == 'title':
  192. save_path = os.path.join(save_path, '%(title)s.%(ext)s')
  193. else:
  194. save_path = os.path.join(save_path, options_dict['output_template'])
  195. options_dict['save_path'] = save_path
  196. def _build_videoformat(self, options_dict):
  197. """Build the video format.
  198. We use this method to build the value of the 'video_format' option and
  199. store it back to the options dictionary.
  200. Args:
  201. options_dict (dictionary): Copy of the original options dictionary.
  202. """
  203. first_vf = VIDEO_FORMATS[options_dict['video_format']]
  204. second_vf = VIDEO_FORMATS[options_dict['second_video_format']]
  205. if first_vf != '0' and second_vf != '0':
  206. options_dict['video_format'] = first_vf + '+' + second_vf
  207. elif first_vf != '0' and second_vf == '0':
  208. options_dict['video_format'] = first_vf
  209. else:
  210. options_dict['video_format'] = ''
  211. def _build_subslang(self, options_dict):
  212. """Build the subtitles language option value.
  213. We use this method to build the value of the 'subs_lang' option and
  214. store it back to the options dictionary.
  215. Args:
  216. options_dict (dictionary): Copy of the original options dictionary.
  217. """
  218. options_dict['subs_lang'] = SUBS_LANG[options_dict['subs_lang']]
  219. def _build_audioquality(self, options_dict):
  220. """Build the audio quality option value.
  221. We use this method to build the value of the 'audio_quality' option and
  222. store it back to the options dictionary.
  223. Args:
  224. options_dict (dictionary): Copy of the original options dictionary.
  225. """
  226. options_dict['audio_quality'] = AUDIO_QUALITY[options_dict['audio_quality']]
  227. def _build_filesizes(self, options_dict):
  228. """Build the filesize options values.
  229. We use this method to build the values of 'min_filesize' and
  230. 'max_filesize' options and store them back to options dictionary.
  231. Args:
  232. options_dict (dictionary): Copy of the original options dictionary.
  233. """
  234. if options_dict['min_filesize']:
  235. size_unit = FILESIZE_UNITS[options_dict['min_filesize_unit']]
  236. options_dict['min_filesize'] = str(options_dict['min_filesize']) + size_unit
  237. if options_dict['max_filesize']:
  238. size_unit = FILESIZE_UNITS[options_dict['max_filesize_unit']]
  239. options_dict['max_filesize'] = str(options_dict['max_filesize']) + size_unit