def test_audioclip_stereo_max_volume(nchannels, channel_muted): def make_frame(t): frame = [] # build channels (one of each pair muted) for i in range(int(nchannels / 2)): if channel_muted == "left": # if muted channel is left, [0, sound, 0, sound...] frame.append(np.sin(t * 0)) frame.append(np.sin(440 * 2 * np.pi * t)) else: # if muted channel is right, [sound, 0, sound, 0...] frame.append(np.sin(440 * 2 * np.pi * t)) frame.append(np.sin(t * 0)) return np.array(frame).T clip = AudioClip(make_frame, fps=44100, duration=1) max_volume = clip.max_volume(stereo=True) # if `stereo == True`, `AudioClip.max_volume` returns a Numpy array` assert isinstance(max_volume, np.ndarray) assert len(max_volume) == nchannels # check channels muted and with sound for i, channel_max_volume in enumerate(max_volume): if i % 2 == 0: if channel_muted == "left": assert channel_max_volume == 0 else: assert channel_max_volume > 0 else: if channel_muted == "right": assert channel_max_volume == 0 else: assert channel_max_volume > 0
def __init__(self, filename, decode_file=False, buffersize=200000, nbytes=2, fps=44100): AudioClip.__init__(self) self.filename = filename self.reader = FFMPEG_AudioReader( filename, decode_file=decode_file, fps=fps, nbytes=nbytes, buffersize=buffersize, ) self.fps = fps self.duration = self.reader.duration self.end = self.reader.duration self.buffersize = self.reader.buffersize self.filename = filename self.make_frame = lambda t: self.reader.get_frame(t) self.nchannels = self.reader.nchannels
def test_audioclip_mono_max_volume(): # mono make_frame_440 = lambda t: np.sin(440 * 2 * np.pi * t) clip = AudioClip(make_frame_440, duration=1, fps=44100) max_volume = clip.max_volume() assert isinstance(max_volume, float) assert max_volume > 0
def __init__(self, filename, buffersize=200000, nbytes=2, fps=44100): AudioClip.__init__(self) self.filename = filename self.reader = FFMPEG_AudioReader(filename, fps=fps, nbytes=nbytes, bufsize=buffersize + 100) self.fps = fps self.duration = self.reader.duration self.end = self.duration self.nframes = self.reader.nframes self.buffersize = buffersize self.buffer = None self._fstart_buffer = 1 self._buffer_around(1) def gf(t): bufsize = self.buffersize if isinstance(t, np.ndarray): # lazy implementation, but should not cause problems in # 99.99 % of the cases result = np.zeros((len(t), 2)) in_time = (t >= 0) & (t < self.duration) inds = (self.fps * t + 1).astype(int)[in_time] f_tmin, f_tmax = inds.min(), inds.max() if not (0 <= (f_tmin - self._fstart_buffer) < len(self.buffer)): self._buffer_around(f_tmin) elif not (0 <= (f_tmax - self._fstart_buffer) < len(self.buffer)): self._buffer_around(f_tmax) try: tup = in_time.nonzero() inds2 = inds - self._fstart_buffer result[in_time] = self.buffer[inds - self._fstart_buffer] return result except IndexError as error: print("Error: wrong indices in video buffer. Maybe" + " buffer too small.") raise error else: ind = int(self.fps * t) if ind < 0 or ind > self.nframes: # out of time: return 0 return np.zeros(self.nchannels) if not (0 <= (ind - self._fstart_buffer) < len(self.buffer)): # out of the buffer: recenter the buffer self._buffer_around(ind) # read the frame in the buffer return self.buffer[ind - self._fstart_buffer] self.get_frame = gf
def test_audioclip(util, mono_wave): filename = os.path.join(util.TMP_DIR, "audioclip.mp3") audio = AudioClip(mono_wave(440), duration=2, fps=22050) audio.write_audiofile(filename, bitrate="16", logger=None) assert os.path.exists(filename) AudioFileClip(filename)
def test_setaudio(util): clip = ColorClip(size=(100, 60), color=(255, 0, 0), duration=0.5) make_frame_440 = lambda t: [np.sin(440 * 2 * np.pi * t)] audio = AudioClip(make_frame_440, duration=0.5) audio.fps = 44100 clip = clip.with_audio(audio) location = os.path.join(util.TMP_DIR, "setaudio.mp4") clip.write_videofile(location, fps=24) assert os.path.isfile(location)
def __init__(self, filename, buffersize=200000, nbytes=2, fps=44100): AudioClip.__init__(self) self.filename = filename self.reader = FFMPEG_AudioReader(filename,fps=fps,nbytes=nbytes, bufsize=buffersize+100) self.fps = fps self.duration = self.reader.duration self.end = self.duration self.nframes = self.reader.nframes self.buffersize= buffersize self.buffer= None self._fstart_buffer = 1 self._buffer_around(1) def gf(t): bufsize = self.buffersize if isinstance(t,np.ndarray): # lazy implementation, but should not cause problems in # 99.99 % of the cases result = np.zeros((len(t),2)) in_time = (t>=0) & (t < self.duration) inds = (self.fps*t+1).astype(int)[in_time] f_tmin, f_tmax = inds.min(), inds.max() if not (0 <= (f_tmin - self._fstart_buffer) < len(self.buffer)): self._buffer_around(f_tmin) elif not (0 <= (f_tmax - self._fstart_buffer) < len(self.buffer)): self._buffer_around(f_tmax) try: tup = in_time.nonzero() inds2 = inds - self._fstart_buffer result[in_time] = self.buffer[inds - self._fstart_buffer] return result except IndexError as error: print ("Error: wrong indices in video buffer. Maybe"+ " buffer too small.") raise error else: ind = int(self.fps*t) if ind<0 or ind> self.nframes: # out of time: return 0 return np.zeros(self.nchannels) if not (0 <= (ind - self._fstart_buffer) <len(self.buffer)): # out of the buffer: recenter the buffer self._buffer_around(ind) # read the frame in the buffer return self.buffer[ind - self._fstart_buffer] self.get_frame = gf
def test_setaudio(): clip = ColorClip(size=(100, 60), color=(255, 0, 0), duration=0.5) make_frame_440 = lambda t: [sin(440 * 2 * pi * t)] audio = AudioClip(make_frame_440, duration=0.5) audio.fps = 44100 clip = clip.set_audio(audio) location = os.path.join(TMP_DIR, "setaudio.mp4") clip.write_videofile(location, fps=24) assert os.path.isfile(location) close_all_clips(locals())
def test_concatenate_audioclips_render(util, mono_wave): """Concatenated AudioClips through ``concatenate_audioclips`` should return a clip that can be rendered to a file. """ filename = os.path.join(util.TMP_DIR, "concatenate_audioclips.mp3") clip_440 = AudioClip(mono_wave(440), duration=0.01, fps=44100) clip_880 = AudioClip(mono_wave(880), duration=0.000001, fps=22050) concat_clip = concatenate_audioclips((clip_440, clip_880)) concat_clip.write_audiofile(filename, logger=None) assert concat_clip.duration == clip_440.duration + clip_880.duration
def __init__(self, filename, buffersize=200000, nbytes=2, fps=44100): AudioClip.__init__(self) self.filename = filename reader = FFMPEG_AudioReader(filename, fps=fps, nbytes=nbytes, buffersize=buffersize) self.reader = reader self.fps = fps self.duration = reader.duration self.end = reader.duration self.make_frame = lambda t: reader.get_frame(t) self.nchannels = reader.nchannels
def test_audioclip(): make_frame = lambda t: [sin(440 * 2 * pi * t)] audio = AudioClip(make_frame, duration=2, fps=22050) audio.write_audiofile(os.path.join(TMP_DIR, "audioclip.mp3"), bitrate="16") assert os.path.exists(os.path.join(TMP_DIR, "audioclip.mp3")) clip = AudioFileClip(os.path.join(TMP_DIR, "audioclip.mp3")) # TODO Write better tests; find out why the following fail # assert clip.duration == 2 # assert clip.fps == 22050 # assert clip.reader.bitrate == 16 close_all_clips(locals())
def loud_sections( audio_clip: AudioClip, # {{{ chunk_duration: float, threshold: float = .01) -> List[Tuple[float, float]]: '''Finds loud sections in audio_clip. :param audio_clip: the audio_clip to search :param chunk_duration: resolution of search :param threshold: volume cutoff threshold :return: list of sections that contain audio above the threshold. ''' # store sectional data loud_sections = [] current_loud = False for i, chunk in enumerate( audio_clip.iter_chunks(chunk_duration=chunk_duration)): a = np.max(chunk) # use numpy as chunk is an nd array if not current_loud: if a >= threshold: start_loud = i * chunk_duration current_loud = True else: if a < threshold: loud_sections.append((start_loud, i * chunk_duration)) current_loud = False if current_loud: # add last loud section if necessary. loud_sections.append((start_loud, audio_clip.duration)) return loud_sections # }}}
def test_concatenate_audioclips_render(): """Concatenated AudioClips through ``concatenate_audioclips`` should return a clip that can be rendered to a file. """ make_frame_440 = lambda t: [np.sin(440 * 2 * np.pi * t)] make_frame_880 = lambda t: [np.sin(880 * 2 * np.pi * t)] clip_440 = AudioClip(make_frame_440, duration=0.01, fps=44100) clip_880 = AudioClip(make_frame_880, duration=0.000001, fps=22050) concat_clip = concatenate_audioclips((clip_440, clip_880)) concat_clip.write_audiofile( os.path.join(TMP_DIR, "concatenate_audioclips.mp3")) assert concat_clip.duration == clip_440.duration + clip_880.duration close_all_clips(locals())
def test_CompositeAudioClip_by__init__(): """The difference between the CompositeAudioClip returned by ``concatenate_audioclips`` and a CompositeAudioClip created using the class directly, is that audios in ``concatenate_audioclips`` are played one after other and AudioClips passed to CompositeAudioClip can be played at different times, it depends on their ``start`` attributes. """ frequencies = [440, 880, 1760] durations = [2, 5, 1] fpss = [44100, 22050, 11025] starts = [0, 1, 2] clips = [ AudioClip( lambda t: [np.sin(frequency * 2 * np.pi * t)], duration=duration, fps=fps ).with_start(start) for frequency, duration, fps, start in zip(frequencies, durations, fpss, starts) ] compound_clip = CompositeAudioClip(clips) # should return a CompositeAudioClip assert isinstance(compound_clip, CompositeAudioClip) # fps of the greatest fps passed into it assert compound_clip.fps == 44100 # duration depends on clips starts and durations ends = [start + duration for start, duration in zip(starts, durations)] assert compound_clip.duration == max(ends) assert list(compound_clip.ends) == ends assert list(compound_clip.starts) == starts # channels are maximum number of channels of the clips assert compound_clip.nchannels == max(clip.nchannels for clip in clips)
def chunkAudio(self, v): pvc = v.getFullVideo() # create tandem mp3 audio af = workD.append("footage").append("chunks").append(f"chunk_{randomString(7)}.mp3") audioclip = AudioClip(af.aPath()) a = AudioSegment.from_mp3(nameAP) packets = make_chunks(a, chuLenMS) # make 5 minute segments to process simultaneously n = pvc.duration // 300 subclips = list() for i in range(n): ts = n * 300 tf = (n + 1) * 300 tf = max(tf, pvc.duration) subclips.append(pvc.subclip(ts, tf)) self.tmpChunks = list() self.tmpCounter = 0 print(f"chunkAudio session {randomString(4)}") executor = concurrent.futures.ProcessPoolExecutor(61) futures = [executor.submit(self.appendChunks, subclips[i], i) for i in range(len(subclips))] # run code in the meantime concurrent.futures.wait(futures) # order in case concurrent was out of order self.tmpChunks = sorted(self.tmpChunks, key=lambda element: (element[0], element[1])) for i in range(len(self.tmpChunks)): i1 = max(0, i - spreadCalc) i2 = min(len(self.tmpChunks), i + spreadCalc) self.tmpChunks[i].sv = sum(list(map(lambda x: x.volume, self.tmpChunks[i1:i2])) / max(1, i2 - i1)) print(self.tmpChunks) os.remove(af.aPath()) exit()
def test_audioclip_concat(): make_frame_440 = lambda t: [sin(440 * 2 * pi * t)] make_frame_880 = lambda t: [sin(880 * 2 * pi * t)] clip1 = AudioClip(make_frame_440, duration=1, fps=44100) clip2 = AudioClip(make_frame_880, duration=2, fps=22050) concat_clip = concatenate_audioclips((clip1, clip2)) # concatenate_audioclips should return a clip with an fps of the greatest # fps passed into it assert concat_clip.fps == 44100 return # Does run without errors, but the length of the audio is way to long, # so it takes ages to run. concat_clip.write_audiofile(os.path.join(TMP_DIR, "concat_audioclip.mp3"))
def getSubAudio(audio: AudioClip, start: float = 0, end: float = None) -> AudioClip: """ slice AudioClip argument - audio : AudioClip class - start : start time second in audio - end : end time second in audio return - _audio_sub : AudioClip class """ # assert end is not None and start < end, "start time is later than end time" assert end is None or (end is not None and start < end), "start time is later than end time" ''' shbaek, 200118 start time is later than end time 에러 메시지가 뜹니다. audio.ipynb 기준으로 코드 바꿔서 돌렸습니다. ''' _audio_sub = audio.subclip(start, end) return _audio_sub
def __init__(self, filename, buffersize=200000, nbytes=2, fps=44100): AudioClip.__init__(self) self.filename = filename reader = FFMPEG_AudioReader(filename,fps=fps,nbytes=nbytes, buffersize=buffersize) self.reader = reader self.fps = fps self.duracion = reader.duracion self.fin = reader.duracion self.make_frame = lambda t: reader.get_frame(t) self.nchannels = reader.nchannels
def test_find_audio_period(mono_wave, stereo_wave, wave_type): if wave_type == "mono": wave1 = mono_wave(freq=400) wave2 = mono_wave(freq=100) else: wave1 = stereo_wave(left_freq=400, right_freq=220) wave2 = stereo_wave(left_freq=100, right_freq=200) clip = CompositeAudioClip([ AudioClip(make_frame=wave1, duration=0.3, fps=22050), multiply_volume( AudioClip(make_frame=wave2, duration=0.3, fps=22050), 0, end_time=0.1, ), ]) loop_clip = loop(clip, 4) assert round(find_audio_period(loop_clip), 6) == pytest.approx(0.29932, 0.1)
def pitch_shift(audio: AudioClip, steps: int) -> AudioClip: """Shifts an audio clip by a given amount of tone steps. Args: audio (AudioClip): Input audio steps (int): Amount of steps to shift Returns: AudioClip: Pitch shifted audio """ with tempfile.TemporaryDirectory() as tmpdir: tmp_file = os.path.join(tmpdir, "tmp.wav") pitched_file = os.path.join(tmpdir, "pitched.wav") audio.write_audiofile(tmp_file) y, sr = librosa.core.load(tmp_file, audio.fps) y_shifted = librosa.effects.pitch_shift(y, sr, n_steps=steps) librosa.output.write_wav(pitched_file, y_shifted, sr) return AudioFileClip(pitched_file)
def test_preview_methods(): stdout = io.StringIO() with redirect_stdout(stdout): try: preview_module = importlib.import_module( "moviepy.video.io.preview") assert preview_module.preview.__hash__( ) != VideoClip.preview.__hash__() except ImportError: editor_module = importlib.import_module("moviepy.editor") with pytest.raises(ImportError) as exc: VideoClip.preview(True) assert str(exc.value) == "clip.preview requires Pygame installed" with pytest.raises(ImportError) as exc: VideoClip.show(True) assert str(exc.value) == "clip.show requires Pygame installed" with pytest.raises(ImportError) as exc: AudioClip.preview(True) assert str(exc.value) == "clip.preview requires Pygame installed" else: editor_module = importlib.import_module("moviepy.editor") assert (editor_module.VideoClip.preview.__hash__() == preview_module.preview.__hash__()) finally: if "moviepy.editor" in sys.modules: del sys.modules["moviepy.editor"] try: importlib.import_module("matplotlib.pyplot") except ImportError: editor_module = importlib.import_module("moviepy.editor") with pytest.raises(ImportError) as exc: editor_module.sliders() assert str(exc.value) == "sliders requires matplotlib installed" del sys.modules["moviepy.editor"] else: del sys.modules["matplotlib.pyplot"] del sys.modules["moviepy"]
def loud_sections_audio(): '''returns audioclip of different frequency, amplitude sine waves as follows: 0| silent | silent 1| normal tone | normal tone 2| silent | silent 3| high tone | high tone 4| silent | silent 5| low tone | low tone 6| quiet | quiet 7| normal tone | normal tone 8| silent | silent 9| silent | silent ... ''' def make_audio_frame(ts): @np.vectorize def f(t): if t < 1: rv = 0 # silent elif t < 2: rv = np.sin(800 * np.pi * t) # normal tone elif t < 3: rv = 0 # silent elif t < 4: rv = np.sin(1600 * np.pi * t) # high tone elif t < 5: rv = 0 # silent elif t < 6: rv = np.sin(200 * np.pi * t) # low tone elif t < 7: rv = np.sin(800 * np.pi * t) * .4 # quiet (40% volume) elif t < 8: rv = np.sin(800 * np.pi * t) # normal tone else: rv = 0 return rv # for some reason np.sin returns np.float64 here so that is emulated rv = f(ts) if rv.shape == (): # rv is a 0d array return np.float64(rv) return rv return AudioClip(make_audio_frame, duration=100, fps=4200)
def test_audioclip_concat(): if sys.platform.startswith("win"): pytest.skip( "Temporarily skipping on windows because otherwise test suite fails with Invalid Handle Error" ) make_frame_440 = lambda t: [sin(440 * 2 * pi * t)] make_frame_880 = lambda t: [sin(880 * 2 * pi * t)] clip1 = AudioClip(make_frame_440, duration=1, fps=44100) clip2 = AudioClip(make_frame_880, duration=2, fps=22050) concat_clip = concatenate_audioclips((clip1, clip2)) # concatenate_audioclips should return a clip with an fps of the greatest # fps passed into it assert concat_clip.fps == 44100 return # Does run without errors, but the length of the audio is way to long, # so it takes ages to run. concat_clip.write_audiofile(os.path.join(TMP_DIR, "concat_audioclip.mp3"))
def test_audioclip_with_file_concat(): make_frame_440 = lambda t: [sin(440 * 2 * pi * t)] clip1 = AudioClip(make_frame_440, duration=1, fps=44100) clip2 = AudioFileClip("media/crunching.mp3") concat_clip = concatenate_audioclips((clip1, clip2)) return # Fails with strange error # "ValueError: operands could not be broadcast together with # shapes (1993,2) (1993,1993)1 concat_clip.write_audiofile(os.path.join(TMP_DIR, "concat_clip_with_file_audio.mp3"))
def test_concatenate_audioclip_with_audiofileclip(): # stereo A note make_frame = lambda t: np.array( [np.sin(440 * 2 * np.pi * t), np.sin(880 * 2 * np.pi * t)]).T clip1 = AudioClip(make_frame, duration=1, fps=44100) clip2 = AudioFileClip("media/crunching.mp3") concat_clip = concatenate_audioclips((clip1, clip2)) concat_clip.write_audiofile( os.path.join(TMP_DIR, "concat_clip_with_file_audio.mp3")) assert concat_clip.duration == clip1.duration + clip2.duration
def runDownsampling(audio: AudioClip, sr: int = 8000) -> AudioClip: """ Setted sound rate is smaller than audio sound rate. argument - audio : AudioClip class - sr : sound rate that you want return - : downsampling AudioClip class """ assert audio.fps > sr, "Audio sound rate is bigger than sr" return audio.set_fps(sr)
def test_concatenate_audioclip_with_audiofileclip(util, stereo_wave): clip1 = AudioClip( stereo_wave(left_freq=440, right_freq=880), duration=1, fps=44100, ) clip2 = AudioFileClip("media/crunching.mp3") concat_clip = concatenate_audioclips((clip1, clip2)) concat_clip.write_audiofile( os.path.join(util.TMP_DIR, "concat_clip_with_file_audio.mp3"), logger=None, ) assert concat_clip.duration == clip1.duration + clip2.duration
def test_audioclip_with_file_concat(): if sys.platform.startswith("win"): pytest.skip( "Temporarily skipping on windows because otherwise test suite fails with Invalid Handle Error" ) make_frame_440 = lambda t: [sin(440 * 2 * pi * t)] clip1 = AudioClip(make_frame_440, duration=1, fps=44100) clip2 = AudioFileClip("media/crunching.mp3") concat_clip = concatenate_audioclips((clip1, clip2)) return # Fails with strange error # "ValueError: operands could not be broadcast together with # shapes (1993,2) (1993,1993)1 concat_clip.write_audiofile( os.path.join(TMP_DIR, "concat_clip_with_file_audio.mp3"))
def test_concatenate_audioclips_CompositeAudioClip(): """Concatenated AudioClips through ``concatenate_audioclips`` should return a CompositeAudioClip whose attributes should be consistent: - Returns CompositeAudioClip. - Their fps is taken from the maximum of their audios. - Audios are placed one after other: - Duration is the sum of their durations. - Ends are the accumulated sum of their durations. - Starts are the accumulated sum of their durations, but first start is 0 and lastest is ignored. - Channels are the max channels of their clips. """ frequencies = [440, 880, 1760] durations = [2, 5, 1] fpss = [44100, 22050, 11025] clips = [ AudioClip(lambda t: [np.sin(frequency * 2 * np.pi * t)], duration=duration, fps=fps) for frequency, duration, fps in zip(frequencies, durations, fpss) ] concat_clip = concatenate_audioclips(clips) # should return a CompositeAudioClip assert isinstance(concat_clip, CompositeAudioClip) # fps of the greatest fps passed into it assert concat_clip.fps == 44100 # audios placed on after other assert concat_clip.duration == sum(durations) assert list(concat_clip.ends) == list(np.cumsum(durations)) assert list(concat_clip.starts), list(np.cumsum([0, *durations[:-1]])) # channels are maximum number of channels of the clips assert concat_clip.nchannels == max(clip.nchannels for clip in clips) close_all_clips(locals())
def test_videoclip_copy(copy_func): """It must be possible to do a mixed copy of VideoClip using ``clip.copy()``, ``copy.copy(clip)`` and ``copy.deepcopy(clip)``. """ clip = VideoClip() other_clip = VideoClip() for attr in clip.__dict__: # mask and audio are shallow copies that should be initialized if attr in ("mask", "audio"): if attr == "mask": nested_object = BitmapClip([["R"]], duration=0.01) else: nested_object = AudioClip( lambda t: [np.sin(880 * 2 * np.pi * t)], duration=0.01, fps=44100) setattr(clip, attr, nested_object) else: setattr(clip, attr, "foo") copied_clip = copy_func(clip) # VideoClip attributes are copied for attr in copied_clip.__dict__: value = getattr(copied_clip, attr) assert value == getattr(clip, attr) # other instances are not edited assert value != getattr(other_clip, attr) # shallow copies of mask and audio if attr in ("mask", "audio"): for nested_attr in value.__dict__: assert getattr(value, nested_attr) == getattr(getattr(clip, attr), nested_attr) # nested objects of instances copies are not edited assert other_clip.mask is None assert other_clip.audio is None
def getAudioArray(audio: AudioClip) -> np.ndarray: """ convert from AudioClip to numpy array argument - audio : AudioClip class return - _audio_np_mono : only 1 dimention audio data """ _audio_np = audio.to_soundarray() if _audio_np.ndim == 2: _audio_np_mono = np.mean(_audio_np, 1) elif _audio_np.ndim == 1: _audio_np_mono = _audio_np else: raise Exception('audio array dimension is only 1 or 2') assert _audio_np_mono.ndim > 0, "Audio data is empty" return _audio_np_mono
def test_audioclip_mono_max_volume(mono_wave): clip = AudioClip(mono_wave(440), duration=1, fps=44100) max_volume = clip.max_volume() assert isinstance(max_volume, float) assert max_volume > 0
def test_audioclip(): make_frame = lambda t: [sin(440 * 2 * pi * t)] clip = AudioClip(make_frame, duration=2, fps=22050) clip.write_audiofile(os.path.join(TMP_DIR, "audioclip.mp3"))