added --srt-lang; updated README; extended the -g FAQ
This commit is contained in:
		
							parent
							
								
									cfcf32d038
								
							
						
					
					
						commit
						a0432a1e80
					
				
					 3 changed files with 111 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -490,6 +490,8 @@ class FileDownloader(object):
 | 
			
		|||
	updatetime:       Use the Last-modified header to set output file timestamps.
 | 
			
		||||
	writedescription: Write the video description to a .description file
 | 
			
		||||
	writeinfojson:    Write the video description to a .info.json file
 | 
			
		||||
	writesubtitles:   Write the video subtitles to a .srt file
 | 
			
		||||
	subtitleslang:    Language of the subtitles to download
 | 
			
		||||
	"""
 | 
			
		||||
 | 
			
		||||
	params = None
 | 
			
		||||
| 
						 | 
				
			
			@ -681,6 +683,10 @@ class FileDownloader(object):
 | 
			
		|||
		""" Report that the description file is being written """
 | 
			
		||||
		self.to_screen(u'[info] Writing video description to: ' + descfn)
 | 
			
		||||
 | 
			
		||||
	def report_writesubtitles(self, srtfn):
 | 
			
		||||
		""" Report that the subtitles file is being written """
 | 
			
		||||
		self.to_screen(u'[info] Writing video subtitles to: ' + srtfn)
 | 
			
		||||
 | 
			
		||||
	def report_writeinfojson(self, infofn):
 | 
			
		||||
		""" Report that the metadata file has been written """
 | 
			
		||||
		self.to_screen(u'[info] Video description metadata as JSON to: ' + infofn)
 | 
			
		||||
| 
						 | 
				
			
			@ -808,6 +814,21 @@ class FileDownloader(object):
 | 
			
		|||
			except (OSError, IOError):
 | 
			
		||||
				self.trouble(u'ERROR: Cannot write description file ' + descfn)
 | 
			
		||||
				return
 | 
			
		||||
				
 | 
			
		||||
		if self.params.get('writesubtitles', False) and 'subtitles' in info_dict and info_dict['subtitles']:
 | 
			
		||||
			# subtitles download errors are already managed as troubles in relevant IE
 | 
			
		||||
			# that way it will silently go on when used with unsupporting IE 
 | 
			
		||||
			try:
 | 
			
		||||
				srtfn = filename.rsplit('.', 1)[0] + u'.srt'
 | 
			
		||||
				self.report_writesubtitles(srtfn)
 | 
			
		||||
				srtfile = open(_encodeFilename(srtfn), 'wb')
 | 
			
		||||
				try:
 | 
			
		||||
					srtfile.write(info_dict['subtitles'].encode('utf-8'))
 | 
			
		||||
				finally:
 | 
			
		||||
					srtfile.close()
 | 
			
		||||
			except (OSError, IOError):
 | 
			
		||||
				self.trouble(u'ERROR: Cannot write subtitles file ' + descfn)
 | 
			
		||||
				return
 | 
			
		||||
 | 
			
		||||
		if self.params.get('writeinfojson', False):
 | 
			
		||||
			infofn = filename + u'.info.json'
 | 
			
		||||
| 
						 | 
				
			
			@ -1206,6 +1227,10 @@ class YoutubeIE(InfoExtractor):
 | 
			
		|||
		"""Report attempt to download video info webpage."""
 | 
			
		||||
		self._downloader.to_screen(u'[youtube] %s: Downloading video info webpage' % video_id)
 | 
			
		||||
 | 
			
		||||
	def report_video_subtitles_download(self, video_id):
 | 
			
		||||
		"""Report attempt to download video info webpage."""
 | 
			
		||||
		self._downloader.to_screen(u'[youtube] %s: Downloading video subtitles' % video_id)
 | 
			
		||||
 | 
			
		||||
	def report_information_extraction(self, video_id):
 | 
			
		||||
		"""Report attempt to extract video information."""
 | 
			
		||||
		self._downloader.to_screen(u'[youtube] %s: Extracting video information' % video_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -1218,6 +1243,23 @@ class YoutubeIE(InfoExtractor):
 | 
			
		|||
		"""Indicate the download will use the RTMP protocol."""
 | 
			
		||||
		self._downloader.to_screen(u'[youtube] RTMP download detected')
 | 
			
		||||
 | 
			
		||||
	def _closed_captions_xml_to_srt(self, xml_string):
 | 
			
		||||
		srt = ''
 | 
			
		||||
		texts = re.findall(r'<text start="([\d\.]+)"( dur="([\d\.]+)")?>([^<]+)</text>', xml_string, re.MULTILINE)
 | 
			
		||||
		# TODO parse xml instead of regex
 | 
			
		||||
		for n, (start, dur_tag, dur, caption) in enumerate(texts):
 | 
			
		||||
			if not dur: dur = '4'
 | 
			
		||||
			start = float(start)
 | 
			
		||||
			end = start + float(dur)
 | 
			
		||||
			start = "%02i:%02i:%02i,%03i" %(start/(60*60), start/60%60, start%60, start%1*1000)
 | 
			
		||||
			end = "%02i:%02i:%02i,%03i" %(end/(60*60), end/60%60, end%60, end%1*1000)
 | 
			
		||||
			caption = re.sub(ur'(?u)&(.+?);', htmlentity_transform, caption)
 | 
			
		||||
			caption = re.sub(ur'(?u)&(.+?);', htmlentity_transform, caption) # double cycle, inentional
 | 
			
		||||
			srt += str(n) + '\n'
 | 
			
		||||
			srt += start + ' --> ' + end + '\n'
 | 
			
		||||
			srt += caption + '\n\n'
 | 
			
		||||
		return srt
 | 
			
		||||
 | 
			
		||||
	def _print_formats(self, formats):
 | 
			
		||||
		print 'Available formats:'
 | 
			
		||||
		for x in formats:
 | 
			
		||||
| 
						 | 
				
			
			@ -1389,6 +1431,37 @@ class YoutubeIE(InfoExtractor):
 | 
			
		|||
			vwebpage_doc = lxml.etree.parse(StringIO.StringIO(video_webpage), html_parser)
 | 
			
		||||
			video_description = u''.join(vwebpage_doc.xpath('id("eow-description")//text()'))
 | 
			
		||||
			# TODO use another parser
 | 
			
		||||
			
 | 
			
		||||
		# closed captions
 | 
			
		||||
		video_subtitles = None
 | 
			
		||||
		if self._downloader.params.get('writesubtitles', False):
 | 
			
		||||
			self.report_video_subtitles_download(video_id)
 | 
			
		||||
			request = urllib2.Request('http://video.google.com/timedtext?hl=en&type=list&v=%s' % video_id)
 | 
			
		||||
			try:
 | 
			
		||||
				srt_list = urllib2.urlopen(request).read()
 | 
			
		||||
			except (urllib2.URLError, httplib.HTTPException, socket.error), err:
 | 
			
		||||
				self._downloader.trouble(u'WARNING: unable to download video subtitles: %s' % str(err))
 | 
			
		||||
			else:
 | 
			
		||||
				srt_lang_list = re.findall(r'lang_code="([\w\-]+)"', srt_list)
 | 
			
		||||
				if srt_lang_list:
 | 
			
		||||
					if self._downloader.params.get('subtitleslang', False):
 | 
			
		||||
						srt_lang = self._downloader.params.get('subtitleslang')
 | 
			
		||||
					elif 'en' in srt_lang_list:
 | 
			
		||||
						srt_lang = 'en'
 | 
			
		||||
					else:
 | 
			
		||||
						srt_lang = srt_lang_list[0]
 | 
			
		||||
					if not srt_lang in srt_lang_list:
 | 
			
		||||
						self._downloader.trouble(u'WARNING: no closed captions found in the specified language')
 | 
			
		||||
					else:
 | 
			
		||||
						request = urllib2.Request('http://video.google.com/timedtext?hl=en&lang=%s&v=%s' % (srt_lang, video_id))
 | 
			
		||||
						try:
 | 
			
		||||
							srt_xml = urllib2.urlopen(request).read()
 | 
			
		||||
						except (urllib2.URLError, httplib.HTTPException, socket.error), err:
 | 
			
		||||
							self._downloader.trouble(u'WARNING: unable to download video subtitles: %s' % str(err))
 | 
			
		||||
						else:
 | 
			
		||||
							video_subtitles = self._closed_captions_xml_to_srt(srt_xml.decode('utf-8'))
 | 
			
		||||
				else:
 | 
			
		||||
					self._downloader.trouble(u'WARNING: video has no closed captions')
 | 
			
		||||
 | 
			
		||||
		# token
 | 
			
		||||
		video_token = urllib.unquote_plus(video_info['token'][0])
 | 
			
		||||
| 
						 | 
				
			
			@ -1461,6 +1534,7 @@ class YoutubeIE(InfoExtractor):
 | 
			
		|||
					'thumbnail':	video_thumbnail.decode('utf-8'),
 | 
			
		||||
					'description':	video_description,
 | 
			
		||||
					'player_url':	player_url,
 | 
			
		||||
					'subtitles':	video_subtitles
 | 
			
		||||
				})
 | 
			
		||||
			except UnavailableVideoError, err:
 | 
			
		||||
				self._downloader.trouble(u'\nERROR: unable to download video')
 | 
			
		||||
| 
						 | 
				
			
			@ -4319,6 +4393,12 @@ def parseOpts():
 | 
			
		|||
			action='store', dest='format_limit', metavar='FORMAT', help='highest quality format to download')
 | 
			
		||||
	video_format.add_option('-F', '--list-formats',
 | 
			
		||||
			action='store_true', dest='listformats', help='list all available formats (currently youtube only)')
 | 
			
		||||
	video_format.add_option('--write-srt',
 | 
			
		||||
			action='store_true', dest='writesubtitles',
 | 
			
		||||
			help='write video closed captions to a .srt file (currently youtube only)', default=False)
 | 
			
		||||
	video_format.add_option('--srt-lang',
 | 
			
		||||
			action='store', dest='subtitleslang', metavar='LANG',
 | 
			
		||||
			help='language of the closed captions to download (optional) use IETF language tags like \'en\'')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	verbosity.add_option('-q', '--quiet',
 | 
			
		||||
| 
						 | 
				
			
			@ -4583,6 +4663,8 @@ def _real_main():
 | 
			
		|||
		'updatetime': opts.updatetime,
 | 
			
		||||
		'writedescription': opts.writedescription,
 | 
			
		||||
		'writeinfojson': opts.writeinfojson,
 | 
			
		||||
		'writesubtitles': opts.writesubtitles,
 | 
			
		||||
		'subtitleslang': opts.subtitleslang,
 | 
			
		||||
		'matchtitle': opts.matchtitle,
 | 
			
		||||
		'rejecttitle': opts.rejecttitle,
 | 
			
		||||
		'max_downloads': opts.max_downloads,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue