From 43cd9db66cbfef95f29cab1581d0a049a692d350 Mon Sep 17 00:00:00 2001 From: Michael Gygli Date: Tue, 4 Apr 2017 13:38:49 +0200 Subject: [PATCH] Audio error handling made failsafe (#377) * audio error handling made failsafe, as for video * fixed case when accessing time out of the estimated valid range * Added test video for issue #246 * remove change not directly related to PR --- moviepy/audio/io/readers.py | 26 ++++++++++++++++---------- tests/download_media.py | 5 ++++- tests/test_issues.py | 6 ++++++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/moviepy/audio/io/readers.py b/moviepy/audio/io/readers.py index 86696e368..8e4935ad0 100644 --- a/moviepy/audio/io/readers.py +++ b/moviepy/audio/io/readers.py @@ -1,9 +1,7 @@ import subprocess as sp -import re +import warnings import numpy as np -from moviepy.tools import cvsecs - from moviepy.video.io.ffmpeg_reader import ffmpeg_parse_infos from moviepy.config import get_setting from moviepy.compat import PY3, DEVNULL @@ -162,8 +160,13 @@ def get_frame(self, tt): # elements of t that are actually in the range of the # audio file. - in_time = (tt>=0) & (tt < self.duration) + + # Check that the requested time is in the valid range + if not in_time.any(): + raise IOError("Error in file %s, "%(self.filename)+ + "Accessing time t=%.02f-%.02f seconds, "%(tt[0], tt[-1])+ + "with clip duration=%d seconds, "%self.duration) # The np.round in the next line is super-important. # Removing it results in artifacts in the noise. @@ -184,15 +187,18 @@ def get_frame(self, tt): indices = frames - self.buffer_startframe result[in_time] = self.buffer[indices] return result + except IndexError as error: - if indices.max() > len(self.buffer): - raise IOError("Error reading file '%s', " % self.filename + - "trying to access beyond the end of the file") - else: - raise IOError("Error in file %s, "%(self.filename)+ + warnings.warn("Error in file %s, "%(self.filename)+ "At time t=%.02f-%.02f seconds, "%(tt[0], tt[-1])+ "indices wanted: %d-%d, "%(indices.min(), indices.max())+ - "but len(buffer)=%d\n"%(len(self.buffer))+ str(error)) + "but len(buffer)=%d\n"%(len(self.buffer))+ str(error), + UserWarning) + + # repeat the last frame instead + indices[indices>=len(self.buffer)] = len(self.buffer) -1 + result[in_time] = self.buffer[indices] + return result else: diff --git a/tests/download_media.py b/tests/download_media.py index 5a6579341..9b875a719 100644 --- a/tests/download_media.py +++ b/tests/download_media.py @@ -36,6 +36,9 @@ def download(): download_url("https://github.com/earney/moviepy_media/raw/master/tests/images/pigs_in_a_polka.gif", "media/pigs_in_a_polka.gif") + + download_url("https://data.vision.ee.ethz.ch/cvl/video2gif/kAKZeIzs0Ag.mp4", + "media/video_with_failing_audio.mp4") download_url("https://github.com/earney/moviepy_media/raw/master/tests/videos/fire2.mp4", - "media/fire2.mp4") + "media/fire2.mp4") \ No newline at end of file diff --git a/tests/test_issues.py b/tests/test_issues.py index 3281338b6..c6237e7e0 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -146,6 +146,12 @@ def test_issue_470(): subclip = audio_clip.subclip(t_start=6, t_end=8) subclip.write_audiofile(os.path.join(TMP_DIR, 'issue_470.wav'), write_logfile=True) +def test_issue_246(): + def test_audio_reader(): + video = VideoFileClip('media/video_with_failing_audio.mp4') + subclip = video.subclip(270) + subclip.write_audiofile(os.path.join(TMP_DIR, 'issue_246.wav'), + write_logfile=True) if __name__ == '__main__': pytest.main()