def testFFmpegAudioAnalyzer(self): from klangbecken.playlist import ffmpeg_audio_analyzer test_data = [ {"prefix": "padded", "gain": -17, "cue_in": 0.2, "cue_out": 0.8}, {"prefix": "padded-start", "gain": -3.33, "cue_in": 1, "cue_out": 2}, {"prefix": "padded-end", "gain": -3.55, "cue_in": 0, "cue_out": 1}, {"prefix": "sine-unicode", "gain": -14, "cue_in": 0, "cue_out": 5}, {"prefix": "interleaved", "gain": -14.16, "cue_in": 0.2, "cue_out": 0.8}, {"prefix": "unpadded-interleaved", "gain": -14, "cue_in": 0, "cue_out": 10}, ] for data in test_data: for ext in "-jointstereo.mp3 -stereo.mp3".split(): self._analyzeOneFile(postfix=ext, **data) # silence only file with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join( self.current_path, "audio", "silence-unicode-stereo.mp3" ) ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn("track only contains silence", cm.exception.description.lower()) # invalid file with self.assertRaises(UnprocessableEntity): ffmpeg_audio_analyzer("music", "id1", "mp3", self.invalid_file)
def _analyzeOneFile(self, prefix, postfix, gain, cue_in, cue_out): from klangbecken.playlist import MetadataChange, ffmpeg_audio_analyzer name = prefix + postfix.split(".")[0] ext = postfix.split(".")[1] path = os.path.join(self.current_path, "audio", name + "." + ext) changes = ffmpeg_audio_analyzer("jingles", name, ext, path) self.assertEqual(len(changes), 6) for change in changes: self.assertIsInstance(change, MetadataChange) changes = {key: val for key, val in changes} self.assertEqual( set(changes.keys()), set("channels samplerate bitrate track_gain cue_in cue_out".split()), ) # Track gain negativ and with units measured_gain = changes["track_gain"] self.assertTrue(measured_gain.endswith(" dB")) # Be within ±0.5 dB of expected gain value self.assertLess(abs(float(measured_gain[:-3]) - gain), 0.5) # Be within the expected values for cue points # Don't fade in late, or fade out early! self.assertGreater(float(changes["cue_in"]), cue_in - 0.1) self.assertLess(float(changes["cue_in"]), cue_in + 0.01) self.assertGreater(float(changes["cue_out"]), cue_out - 0.02) self.assertLess(float(changes["cue_out"]), cue_out + 0.1)
def testFFmpegAudioAnalyzerAudioQuality(self): from klangbecken.playlist import ffmpeg_audio_analyzer with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "not-an-audio-file.mp3") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn("cannot process audio data", cm.exception.description.lower()) with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "silence.wav") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn( "the track is not a valid mp3 file", cm.exception.description.lower() ) self.assertIn("ulaw", cm.exception.description.lower()) with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "silence.ogg") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn( "the track is not a valid mp3 file", cm.exception.description.lower() ) self.assertIn("vorbis", cm.exception.description.lower()) with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "silence-32kHz.mp3") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn("invalid sample rate: 32", cm.exception.description.lower()) with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "sine-unicode-mono.mp3") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn("stereo", cm.exception.description.lower()) path = os.path.join(self.current_path, "audio", "sine-unicode-mono.mp3") changes = ffmpeg_audio_analyzer("jingles", "id1", "mp3", path) self.assertEqual(len(changes), 6) with self.assertRaises(UnprocessableEntity) as cm: path = os.path.join(self.current_path, "audio", "silence-112kbps.mp3") ffmpeg_audio_analyzer("music", "id1", "mp3", path) self.assertIn("bitrate too low: 112 < 128", cm.exception.description.lower())