We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
--audio-quality not working as intended
Hello,
I'm using the following command to download video and convert it into mp3:

youtube-dl -t --extract-audio --audio-format mp3 --audio-quality 256k --max-quality 37 http://www.youtube.com/watch?v=xxxxxxxxx

The problem i have is that every mp3 has 128kbs compression ratio. Before the latest update (youtube and youtube-dl) worked flawlessly.
I tried every command without success, if i miss the quality it gets the mp3 at 28kbs.
i tried even downloading same video that worked before.

Ubuntu server 12 with Python 2.7.3


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `youtube_dl/PostProcessor.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 import os
5 import subprocess
6 import sys
7 import time
8 
9 from utils import *
10 
11 
12 class PostProcessor(object):
13 	"""Post Processor class.
14 
15 	PostProcessor objects can be added to downloaders with their
16 	add_post_processor() method. When the downloader has finished a
17 	successful download, it will take its internal chain of PostProcessors
18 	and start calling the run() method on each one of them, first with
19 	an initial argument and then with the returned value of the previous
20 	PostProcessor.
21 
22 	The chain will be stopped if one of them ever returns None or the end
23 	of the chain is reached.
24 
25 	PostProcessor objects follow a "mutual registration" process similar
26 	to InfoExtractor objects.
27 	"""
28 
29 	_downloader = None
30 
31 	def __init__(self, downloader=None):
32 		self._downloader = downloader
33 
34 	def set_downloader(self, downloader):
35 		"""Sets the downloader for this PP."""
36 		self._downloader = downloader
37 
38 	def run(self, information):
39 		"""Run the PostProcessor.
40 
41 		The "information" argument is a dictionary like the ones
42 		composed by InfoExtractors. The only difference is that this
43 		one has an extra field called "filepath" that points to the
44 		downloaded file.
45 
46 		When this method returns None, the postprocessing chain is
47 		stopped. However, this method may return an information
48 		dictionary that will be passed to the next postprocessing
49 		object in the chain. It can be the one it received after
50 		changing some fields.
51 
52 		In addition, this method may raise a PostProcessingError
53 		exception that will be taken into account by the downloader
54 		it was called from.
55 		"""
56 		return information # by default, do nothing
57 
58 class AudioConversionError(BaseException):
59 	def __init__(self, message):
60 		self.message = message
61 
62 class FFmpegExtractAudioPP(PostProcessor):
63 	def __init__(self, downloader=None, preferredcodec=None, preferredquality=None, keepvideo=False):
64 		PostProcessor.__init__(self, downloader)
65 		if preferredcodec is None:
66 			preferredcodec = 'best'
67 		self._preferredcodec = preferredcodec
68 		self._preferredquality = preferredquality
69 		self._keepvideo = keepvideo
70 		self._exes = self.detect_executables()
71 
72 	@staticmethod
73 	def detect_executables():
74 		def executable(exe):
75 			try:
76 				subprocess.Popen([exe, '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
77 			except OSError:
78 				return False
79 			return exe
80 		programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']
81 		return dict((program, executable(program)) for program in programs)
82 
83 	def get_audio_codec(self, path):
84 		if not self._exes['ffprobe'] and not self._exes['avprobe']: return None
85 		try:
86 			cmd = [self._exes['avprobe'] or self._exes['ffprobe'], '-show_streams', '--', encodeFilename(path)]
87 			handle = subprocess.Popen(cmd, stderr=file(os.path.devnull, 'w'), stdout=subprocess.PIPE)
88 			output = handle.communicate()[0]
89 			if handle.wait() != 0:
90 				return None
91 		except (IOError, OSError):
92 			return None
93 		audio_codec = None
94 		for line in output.split('\n'):
95 			if line.startswith('codec_name='):
96 				audio_codec = line.split('=')[1].strip()
97 			elif line.strip() == 'codec_type=audio' and audio_codec is not None:
98 				return audio_codec
99 		return None
100 
101 	def run_ffmpeg(self, path, out_path, codec, more_opts):
102 		if not self._exes['ffmpeg'] and not self._exes['avconv']:
103 			raise AudioConversionError('ffmpeg or avconv not found. Please install one.')	
104 		if codec is None:
105 			acodec_opts = []
106 		else:
107 			acodec_opts = ['-acodec', codec]
108 		cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y', '-i', encodeFilename(path), '-vn']
109 			   + acodec_opts + more_opts +
110 			   ['--', encodeFilename(out_path)])
111 		p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
112 		stdout,stderr = p.communicate()
113 		if p.returncode != 0:
114 			msg = stderr.strip().split('\n')[-1]
115 			raise AudioConversionError(msg)
116 
117 	def run(self, information):
118 		path = information['filepath']
119 
120 		filecodec = self.get_audio_codec(path)
121 		if filecodec is None:
122 			self._downloader.to_stderr(u'WARNING: unable to obtain file audio codec with ffprobe')
123 			return None
124 
125 		more_opts = []
126 		if self._preferredcodec == 'best' or self._preferredcodec == filecodec or (self._preferredcodec == 'm4a' and filecodec == 'aac'):
127 			if self._preferredcodec == 'm4a' and filecodec == 'aac':
128 				# Lossless, but in another container
129 				acodec = 'copy'
130 				extension = self._preferredcodec
131 				more_opts = [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']
132 			elif filecodec in ['aac', 'mp3', 'vorbis']:
133 				# Lossless if possible
134 				acodec = 'copy'
135 				extension = filecodec
136 				if filecodec == 'aac':
137 					more_opts = ['-f', 'adts']
138 				if filecodec == 'vorbis':
139 					extension = 'ogg'
140 			else:
141 				# MP3 otherwise.
142 				acodec = 'libmp3lame'
143 				extension = 'mp3'
144 				more_opts = []
145 				if self._preferredquality is not None:
146 					if int(self._preferredquality) < 10:
147 						more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
148 					else:
149 						more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]
150 		else:
151 			# We convert the audio (lossy)
152 			acodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]
153 			extension = self._preferredcodec
154 			more_opts = []
155 			if self._preferredquality is not None:
156 				if int(self._preferredquality) < 10:
157 					more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
158 				else:
159 					more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]
160 			if self._preferredcodec == 'aac':
161 				more_opts += ['-f', 'adts']
162 			if self._preferredcodec == 'm4a':
163 				more_opts += [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']
164 			if self._preferredcodec == 'vorbis':
165 				extension = 'ogg'
166 			if self._preferredcodec == 'wav':
167 				extension = 'wav'
168 				more_opts += ['-f', 'wav']
169 
170 		prefix, sep, ext = path.rpartition(u'.') # not os.path.splitext, since the latter does not work on unicode in all setups
171 		new_path = prefix + sep + extension
172 		self._downloader.to_screen(u'[' + (self._exes['avconv'] and 'avconv' or 'ffmpeg') + '] Destination: ' + new_path)
173 		try:
174 			self.run_ffmpeg(path, new_path, acodec, more_opts)
175 		except:
176 			etype,e,tb = sys.exc_info()
177 			if isinstance(e, AudioConversionError):
178 				self._downloader.to_stderr(u'ERROR: audio conversion failed: ' + e.message)
179 			else:
180 				self._downloader.to_stderr(u'ERROR: error running ' + (self._exes['avconv'] and 'avconv' or 'ffmpeg'))
181 			return None
182 
183  		# Try to update the date time for extracted audio file.
184 		if information.get('filetime') is not None:
185 			try:
186 				os.utime(encodeFilename(new_path), (time.time(), information['filetime']))
187 			except:
188 				self._downloader.to_stderr(u'WARNING: Cannot update utime of audio file')
189 
190 		if not self._keepvideo:
191 			try:
192 				os.remove(encodeFilename(path))
193 			except (IOError, OSError):
194 				self._downloader.to_stderr(u'WARNING: Unable to remove downloaded video file')
195 				return None
196 
197 		information['filepath'] = new_path
198 		return information
199
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/youtube_dl/PostProcessor.py b/youtube_dl/PostProcessor.py
--- a/youtube_dl/PostProcessor.py
+++ b/youtube_dl/PostProcessor.py
@@ -146,7 +146,7 @@
 					if int(self._preferredquality) < 10:
 						more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
 					else:
-						more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]
+						more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']
 		else:
 			# We convert the audio (lossy)
 			acodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]
@@ -156,7 +156,7 @@
 				if int(self._preferredquality) < 10:
 					more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
 				else:
-					more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]
+					more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']
 			if self._preferredcodec == 'aac':
 				more_opts += ['-f', 'adts']
 			if self._preferredcodec == 'm4a':

{"golden_diff": "diff --git a/youtube_dl/PostProcessor.py b/youtube_dl/PostProcessor.py\n--- a/youtube_dl/PostProcessor.py\n+++ b/youtube_dl/PostProcessor.py\n@@ -146,7 +146,7 @@\n \t\t\t\t\tif int(self._preferredquality) < 10:\n \t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n \t\t\t\t\telse:\n-\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]\n+\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']\n \t\telse:\n \t\t\t# We convert the audio (lossy)\n \t\t\tacodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]\n@@ -156,7 +156,7 @@\n \t\t\t\tif int(self._preferredquality) < 10:\n \t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n \t\t\t\telse:\n-\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]\n+\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']\n \t\t\tif self._preferredcodec == 'aac':\n \t\t\t\tmore_opts += ['-f', 'adts']\n \t\t\tif self._preferredcodec == 'm4a':\n", "issue": "--audio-quality not working as intended\nHello,\nI'm using the following command to download video and convert it into mp3:\n\nyoutube-dl -t --extract-audio --audio-format mp3 --audio-quality 256k --max-quality 37 http://www.youtube.com/watch?v=xxxxxxxxx\n\nThe problem i have is that every mp3 has 128kbs compression ratio. Before the latest update (youtube and youtube-dl) worked flawlessly.\nI tried every command without success, if i miss the quality it gets the mp3 at 28kbs.\ni tried even downloading same video that worked before.\n\nUbuntu server 12 with Python 2.7.3\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport os\nimport subprocess\nimport sys\nimport time\n\nfrom utils import *\n\n\nclass PostProcessor(object):\n\t\"\"\"Post Processor class.\n\n\tPostProcessor objects can be added to downloaders with their\n\tadd_post_processor() method. When the downloader has finished a\n\tsuccessful download, it will take its internal chain of PostProcessors\n\tand start calling the run() method on each one of them, first with\n\tan initial argument and then with the returned value of the previous\n\tPostProcessor.\n\n\tThe chain will be stopped if one of them ever returns None or the end\n\tof the chain is reached.\n\n\tPostProcessor objects follow a \"mutual registration\" process similar\n\tto InfoExtractor objects.\n\t\"\"\"\n\n\t_downloader = None\n\n\tdef __init__(self, downloader=None):\n\t\tself._downloader = downloader\n\n\tdef set_downloader(self, downloader):\n\t\t\"\"\"Sets the downloader for this PP.\"\"\"\n\t\tself._downloader = downloader\n\n\tdef run(self, information):\n\t\t\"\"\"Run the PostProcessor.\n\n\t\tThe \"information\" argument is a dictionary like the ones\n\t\tcomposed by InfoExtractors. The only difference is that this\n\t\tone has an extra field called \"filepath\" that points to the\n\t\tdownloaded file.\n\n\t\tWhen this method returns None, the postprocessing chain is\n\t\tstopped. However, this method may return an information\n\t\tdictionary that will be passed to the next postprocessing\n\t\tobject in the chain. It can be the one it received after\n\t\tchanging some fields.\n\n\t\tIn addition, this method may raise a PostProcessingError\n\t\texception that will be taken into account by the downloader\n\t\tit was called from.\n\t\t\"\"\"\n\t\treturn information # by default, do nothing\n\nclass AudioConversionError(BaseException):\n\tdef __init__(self, message):\n\t\tself.message = message\n\nclass FFmpegExtractAudioPP(PostProcessor):\n\tdef __init__(self, downloader=None, preferredcodec=None, preferredquality=None, keepvideo=False):\n\t\tPostProcessor.__init__(self, downloader)\n\t\tif preferredcodec is None:\n\t\t\tpreferredcodec = 'best'\n\t\tself._preferredcodec = preferredcodec\n\t\tself._preferredquality = preferredquality\n\t\tself._keepvideo = keepvideo\n\t\tself._exes = self.detect_executables()\n\n\t@staticmethod\n\tdef detect_executables():\n\t\tdef executable(exe):\n\t\t\ttry:\n\t\t\t\tsubprocess.Popen([exe, '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()\n\t\t\texcept OSError:\n\t\t\t\treturn False\n\t\t\treturn exe\n\t\tprograms = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']\n\t\treturn dict((program, executable(program)) for program in programs)\n\n\tdef get_audio_codec(self, path):\n\t\tif not self._exes['ffprobe'] and not self._exes['avprobe']: return None\n\t\ttry:\n\t\t\tcmd = [self._exes['avprobe'] or self._exes['ffprobe'], '-show_streams', '--', encodeFilename(path)]\n\t\t\thandle = subprocess.Popen(cmd, stderr=file(os.path.devnull, 'w'), stdout=subprocess.PIPE)\n\t\t\toutput = handle.communicate()[0]\n\t\t\tif handle.wait() != 0:\n\t\t\t\treturn None\n\t\texcept (IOError, OSError):\n\t\t\treturn None\n\t\taudio_codec = None\n\t\tfor line in output.split('\\n'):\n\t\t\tif line.startswith('codec_name='):\n\t\t\t\taudio_codec = line.split('=')[1].strip()\n\t\t\telif line.strip() == 'codec_type=audio' and audio_codec is not None:\n\t\t\t\treturn audio_codec\n\t\treturn None\n\n\tdef run_ffmpeg(self, path, out_path, codec, more_opts):\n\t\tif not self._exes['ffmpeg'] and not self._exes['avconv']:\n\t\t\traise AudioConversionError('ffmpeg or avconv not found. Please install one.')\t\n\t\tif codec is None:\n\t\t\tacodec_opts = []\n\t\telse:\n\t\t\tacodec_opts = ['-acodec', codec]\n\t\tcmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y', '-i', encodeFilename(path), '-vn']\n\t\t\t   + acodec_opts + more_opts +\n\t\t\t   ['--', encodeFilename(out_path)])\n\t\tp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\t\tstdout,stderr = p.communicate()\n\t\tif p.returncode != 0:\n\t\t\tmsg = stderr.strip().split('\\n')[-1]\n\t\t\traise AudioConversionError(msg)\n\n\tdef run(self, information):\n\t\tpath = information['filepath']\n\n\t\tfilecodec = self.get_audio_codec(path)\n\t\tif filecodec is None:\n\t\t\tself._downloader.to_stderr(u'WARNING: unable to obtain file audio codec with ffprobe')\n\t\t\treturn None\n\n\t\tmore_opts = []\n\t\tif self._preferredcodec == 'best' or self._preferredcodec == filecodec or (self._preferredcodec == 'm4a' and filecodec == 'aac'):\n\t\t\tif self._preferredcodec == 'm4a' and filecodec == 'aac':\n\t\t\t\t# Lossless, but in another container\n\t\t\t\tacodec = 'copy'\n\t\t\t\textension = self._preferredcodec\n\t\t\t\tmore_opts = [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']\n\t\t\telif filecodec in ['aac', 'mp3', 'vorbis']:\n\t\t\t\t# Lossless if possible\n\t\t\t\tacodec = 'copy'\n\t\t\t\textension = filecodec\n\t\t\t\tif filecodec == 'aac':\n\t\t\t\t\tmore_opts = ['-f', 'adts']\n\t\t\t\tif filecodec == 'vorbis':\n\t\t\t\t\textension = 'ogg'\n\t\t\telse:\n\t\t\t\t# MP3 otherwise.\n\t\t\t\tacodec = 'libmp3lame'\n\t\t\t\textension = 'mp3'\n\t\t\t\tmore_opts = []\n\t\t\t\tif self._preferredquality is not None:\n\t\t\t\t\tif int(self._preferredquality) < 10:\n\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n\t\t\t\t\telse:\n\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]\n\t\telse:\n\t\t\t# We convert the audio (lossy)\n\t\t\tacodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]\n\t\t\textension = self._preferredcodec\n\t\t\tmore_opts = []\n\t\t\tif self._preferredquality is not None:\n\t\t\t\tif int(self._preferredquality) < 10:\n\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n\t\t\t\telse:\n\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality]\n\t\t\tif self._preferredcodec == 'aac':\n\t\t\t\tmore_opts += ['-f', 'adts']\n\t\t\tif self._preferredcodec == 'm4a':\n\t\t\t\tmore_opts += [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']\n\t\t\tif self._preferredcodec == 'vorbis':\n\t\t\t\textension = 'ogg'\n\t\t\tif self._preferredcodec == 'wav':\n\t\t\t\textension = 'wav'\n\t\t\t\tmore_opts += ['-f', 'wav']\n\n\t\tprefix, sep, ext = path.rpartition(u'.') # not os.path.splitext, since the latter does not work on unicode in all setups\n\t\tnew_path = prefix + sep + extension\n\t\tself._downloader.to_screen(u'[' + (self._exes['avconv'] and 'avconv' or 'ffmpeg') + '] Destination: ' + new_path)\n\t\ttry:\n\t\t\tself.run_ffmpeg(path, new_path, acodec, more_opts)\n\t\texcept:\n\t\t\tetype,e,tb = sys.exc_info()\n\t\t\tif isinstance(e, AudioConversionError):\n\t\t\t\tself._downloader.to_stderr(u'ERROR: audio conversion failed: ' + e.message)\n\t\t\telse:\n\t\t\t\tself._downloader.to_stderr(u'ERROR: error running ' + (self._exes['avconv'] and 'avconv' or 'ffmpeg'))\n\t\t\treturn None\n\n \t\t# Try to update the date time for extracted audio file.\n\t\tif information.get('filetime') is not None:\n\t\t\ttry:\n\t\t\t\tos.utime(encodeFilename(new_path), (time.time(), information['filetime']))\n\t\t\texcept:\n\t\t\t\tself._downloader.to_stderr(u'WARNING: Cannot update utime of audio file')\n\n\t\tif not self._keepvideo:\n\t\t\ttry:\n\t\t\t\tos.remove(encodeFilename(path))\n\t\t\texcept (IOError, OSError):\n\t\t\t\tself._downloader.to_stderr(u'WARNING: Unable to remove downloaded video file')\n\t\t\t\treturn None\n\n\t\tinformation['filepath'] = new_path\n\t\treturn information\n", "path": "youtube_dl/PostProcessor.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nimport os\nimport subprocess\nimport sys\nimport time\n\nfrom utils import *\n\n\nclass PostProcessor(object):\n\t\"\"\"Post Processor class.\n\n\tPostProcessor objects can be added to downloaders with their\n\tadd_post_processor() method. When the downloader has finished a\n\tsuccessful download, it will take its internal chain of PostProcessors\n\tand start calling the run() method on each one of them, first with\n\tan initial argument and then with the returned value of the previous\n\tPostProcessor.\n\n\tThe chain will be stopped if one of them ever returns None or the end\n\tof the chain is reached.\n\n\tPostProcessor objects follow a \"mutual registration\" process similar\n\tto InfoExtractor objects.\n\t\"\"\"\n\n\t_downloader = None\n\n\tdef __init__(self, downloader=None):\n\t\tself._downloader = downloader\n\n\tdef set_downloader(self, downloader):\n\t\t\"\"\"Sets the downloader for this PP.\"\"\"\n\t\tself._downloader = downloader\n\n\tdef run(self, information):\n\t\t\"\"\"Run the PostProcessor.\n\n\t\tThe \"information\" argument is a dictionary like the ones\n\t\tcomposed by InfoExtractors. The only difference is that this\n\t\tone has an extra field called \"filepath\" that points to the\n\t\tdownloaded file.\n\n\t\tWhen this method returns None, the postprocessing chain is\n\t\tstopped. However, this method may return an information\n\t\tdictionary that will be passed to the next postprocessing\n\t\tobject in the chain. It can be the one it received after\n\t\tchanging some fields.\n\n\t\tIn addition, this method may raise a PostProcessingError\n\t\texception that will be taken into account by the downloader\n\t\tit was called from.\n\t\t\"\"\"\n\t\treturn information # by default, do nothing\n\nclass AudioConversionError(BaseException):\n\tdef __init__(self, message):\n\t\tself.message = message\n\nclass FFmpegExtractAudioPP(PostProcessor):\n\tdef __init__(self, downloader=None, preferredcodec=None, preferredquality=None, keepvideo=False):\n\t\tPostProcessor.__init__(self, downloader)\n\t\tif preferredcodec is None:\n\t\t\tpreferredcodec = 'best'\n\t\tself._preferredcodec = preferredcodec\n\t\tself._preferredquality = preferredquality\n\t\tself._keepvideo = keepvideo\n\t\tself._exes = self.detect_executables()\n\n\t@staticmethod\n\tdef detect_executables():\n\t\tdef executable(exe):\n\t\t\ttry:\n\t\t\t\tsubprocess.Popen([exe, '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()\n\t\t\texcept OSError:\n\t\t\t\treturn False\n\t\t\treturn exe\n\t\tprograms = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']\n\t\treturn dict((program, executable(program)) for program in programs)\n\n\tdef get_audio_codec(self, path):\n\t\tif not self._exes['ffprobe'] and not self._exes['avprobe']: return None\n\t\ttry:\n\t\t\tcmd = [self._exes['avprobe'] or self._exes['ffprobe'], '-show_streams', '--', encodeFilename(path)]\n\t\t\thandle = subprocess.Popen(cmd, stderr=file(os.path.devnull, 'w'), stdout=subprocess.PIPE)\n\t\t\toutput = handle.communicate()[0]\n\t\t\tif handle.wait() != 0:\n\t\t\t\treturn None\n\t\texcept (IOError, OSError):\n\t\t\treturn None\n\t\taudio_codec = None\n\t\tfor line in output.split('\\n'):\n\t\t\tif line.startswith('codec_name='):\n\t\t\t\taudio_codec = line.split('=')[1].strip()\n\t\t\telif line.strip() == 'codec_type=audio' and audio_codec is not None:\n\t\t\t\treturn audio_codec\n\t\treturn None\n\n\tdef run_ffmpeg(self, path, out_path, codec, more_opts):\n\t\tif not self._exes['ffmpeg'] and not self._exes['avconv']:\n\t\t\traise AudioConversionError('ffmpeg or avconv not found. Please install one.')\t\n\t\tif codec is None:\n\t\t\tacodec_opts = []\n\t\telse:\n\t\t\tacodec_opts = ['-acodec', codec]\n\t\tcmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y', '-i', encodeFilename(path), '-vn']\n\t\t\t   + acodec_opts + more_opts +\n\t\t\t   ['--', encodeFilename(out_path)])\n\t\tp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\t\tstdout,stderr = p.communicate()\n\t\tif p.returncode != 0:\n\t\t\tmsg = stderr.strip().split('\\n')[-1]\n\t\t\traise AudioConversionError(msg)\n\n\tdef run(self, information):\n\t\tpath = information['filepath']\n\n\t\tfilecodec = self.get_audio_codec(path)\n\t\tif filecodec is None:\n\t\t\tself._downloader.to_stderr(u'WARNING: unable to obtain file audio codec with ffprobe')\n\t\t\treturn None\n\n\t\tmore_opts = []\n\t\tif self._preferredcodec == 'best' or self._preferredcodec == filecodec or (self._preferredcodec == 'm4a' and filecodec == 'aac'):\n\t\t\tif self._preferredcodec == 'm4a' and filecodec == 'aac':\n\t\t\t\t# Lossless, but in another container\n\t\t\t\tacodec = 'copy'\n\t\t\t\textension = self._preferredcodec\n\t\t\t\tmore_opts = [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']\n\t\t\telif filecodec in ['aac', 'mp3', 'vorbis']:\n\t\t\t\t# Lossless if possible\n\t\t\t\tacodec = 'copy'\n\t\t\t\textension = filecodec\n\t\t\t\tif filecodec == 'aac':\n\t\t\t\t\tmore_opts = ['-f', 'adts']\n\t\t\t\tif filecodec == 'vorbis':\n\t\t\t\t\textension = 'ogg'\n\t\t\telse:\n\t\t\t\t# MP3 otherwise.\n\t\t\t\tacodec = 'libmp3lame'\n\t\t\t\textension = 'mp3'\n\t\t\t\tmore_opts = []\n\t\t\t\tif self._preferredquality is not None:\n\t\t\t\t\tif int(self._preferredquality) < 10:\n\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n\t\t\t\t\telse:\n\t\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']\n\t\telse:\n\t\t\t# We convert the audio (lossy)\n\t\t\tacodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]\n\t\t\textension = self._preferredcodec\n\t\t\tmore_opts = []\n\t\t\tif self._preferredquality is not None:\n\t\t\t\tif int(self._preferredquality) < 10:\n\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]\n\t\t\t\telse:\n\t\t\t\t\tmore_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']\n\t\t\tif self._preferredcodec == 'aac':\n\t\t\t\tmore_opts += ['-f', 'adts']\n\t\t\tif self._preferredcodec == 'm4a':\n\t\t\t\tmore_opts += [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']\n\t\t\tif self._preferredcodec == 'vorbis':\n\t\t\t\textension = 'ogg'\n\t\t\tif self._preferredcodec == 'wav':\n\t\t\t\textension = 'wav'\n\t\t\t\tmore_opts += ['-f', 'wav']\n\n\t\tprefix, sep, ext = path.rpartition(u'.') # not os.path.splitext, since the latter does not work on unicode in all setups\n\t\tnew_path = prefix + sep + extension\n\t\tself._downloader.to_screen(u'[' + (self._exes['avconv'] and 'avconv' or 'ffmpeg') + '] Destination: ' + new_path)\n\t\ttry:\n\t\t\tself.run_ffmpeg(path, new_path, acodec, more_opts)\n\t\texcept:\n\t\t\tetype,e,tb = sys.exc_info()\n\t\t\tif isinstance(e, AudioConversionError):\n\t\t\t\tself._downloader.to_stderr(u'ERROR: audio conversion failed: ' + e.message)\n\t\t\telse:\n\t\t\t\tself._downloader.to_stderr(u'ERROR: error running ' + (self._exes['avconv'] and 'avconv' or 'ffmpeg'))\n\t\t\treturn None\n\n \t\t# Try to update the date time for extracted audio file.\n\t\tif information.get('filetime') is not None:\n\t\t\ttry:\n\t\t\t\tos.utime(encodeFilename(new_path), (time.time(), information['filetime']))\n\t\t\texcept:\n\t\t\t\tself._downloader.to_stderr(u'WARNING: Cannot update utime of audio file')\n\n\t\tif not self._keepvideo:\n\t\t\ttry:\n\t\t\t\tos.remove(encodeFilename(path))\n\t\t\texcept (IOError, OSError):\n\t\t\t\tself._downloader.to_stderr(u'WARNING: Unable to remove downloaded video file')\n\t\t\t\treturn None\n\n\t\tinformation['filepath'] = new_path\n\t\treturn information\n", "path": "youtube_dl/PostProcessor.py"}]}