Skip to content

Commit

Permalink
documentation - add function audio2wav
Browse files Browse the repository at this point in the history
  • Loading branch information
sdpython committed Jan 15, 2018
1 parent 5119bb8 commit 182021b
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 18 deletions.
1 change: 1 addition & 0 deletions .local.jenkins.win.yml
Expand Up @@ -17,6 +17,7 @@ script:
- { CMD: "python -u setup.py unittests -e \".*noenv4.*\"", NAME: "UT_NOENV4" }
- { CMD: "python -u setup.py unittests -e \".*noenv5.*\"", NAME: "UT_NOENV5" }
- { CMD: "python -u setup.py unittests -e \".*noenv6.*\"", NAME: "UT_NOENV6" }
- { CMD: "python -u setup.py unittests -e \".*noenv7.*\"", NAME: "UT_NOENV7" }
- { CMD: "python -X faulthandler -X showrefcount -u setup.py unittests_LONG", NAME: "UT_LONG" }
- { CMD: "python -X faulthandler -X showrefcount -u setup.py unittests_SKIP", NAME: "UT_SKIP" }
after_script:
Expand Down
2 changes: 2 additions & 0 deletions _doc/sphinxdoc/source/conf.py
Expand Up @@ -74,6 +74,7 @@
html_split_index = True

epkg_dictionary['AudioClip'] = 'https://zulko.github.io/moviepy/ref/AudioClip/AudioClip.html'
epkg_dictionary['AudioArrayClip'] = 'https://zulko.github.io/moviepy/ref/AudioClip/AudioClip.html'
epkg_dictionary['deep learning'] = 'https://en.wikipedia.org/wiki/Deep_learning'
epkg_dictionary['fcn'] = 'https://github.com/wkentaro/fcn'
epkg_dictionary['gif'] = 'https://fr.wikipedia.org/wiki/Graphics_Interchange_Format'
Expand All @@ -90,3 +91,4 @@
epkg_dictionary['VLC'] = 'https://www.videolan.org/vlc/index.html'
epkg_dictionary['YouTube'] = "https://www.youtube.com/"
epkg_dictionary['youtube'] = "https://www.youtube.com/"
epkg_dictionary['wav'] = "https://fr.wikipedia.org/wiki/Waveform_Audio_File_Format"
16 changes: 12 additions & 4 deletions _unittests/ut_art/test_video_noenv2_audio.py
Expand Up @@ -46,7 +46,8 @@

from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import get_temp_folder, ExtTestCase
from src.code_beatrix.art.video import video_save, video_replace_audio, video_extract_audio, video_remove_audio
from src.code_beatrix.art.video import video_save, video_replace_audio, video_extract_audio
from src.code_beatrix.art.video import video_remove_audio, audio_modification, audio_save, audio2wav


class TestAudioVideo(ExtTestCase):
Expand All @@ -60,11 +61,18 @@ def test_extract_audio_video(self):
vid = os.path.join(temp, '..', 'data', 'videxa.mp4')
aud = os.path.join(temp, '..', 'data', 'cartoon011.wav')
vid = video_remove_audio(vid)
vid2 = video_replace_audio(vid, aud, loop=True, volumex=5.5, fadein=True,
t_end='00:00:05', speed=2.)
audio2 = audio_modification(aud, volumex=5.5, fadein=True,
speed=2., keep_duration=False,
loop_duration=True)
vid2 = video_replace_audio(vid, audio2, loop=False)
self.assertTrue(video_extract_audio(vid2) is not None)
exp = os.path.join(temp, "courte_audio.mp4")
video_save(vid2, exp, verbose=False)
video_save(vid2, exp, verbose=__name__ == "__main__", duration=2)
self.assertExists(exp)

audio3 = audio2wav(audio2, duration=5, fps=44100)
exp = os.path.join(temp, "courte_audio.mp3")
audio_save(audio3, exp, verbose=__name__ == "__main__")
self.assertExists(exp)


Expand Down
File renamed without changes.
56 changes: 42 additions & 14 deletions src/code_beatrix/art/video.py
Expand Up @@ -19,7 +19,7 @@
from moviepy.audio.AudioClip import CompositeAudioClip
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from moviepy.video.compositing.concatenate import concatenate_videoclips
from moviepy.audio.AudioClip import concatenate_audioclips
from moviepy.audio.AudioClip import concatenate_audioclips, AudioArrayClip
from .moviepy_context import AudioContext, VideoContext
from PIL import Image, ImageFont, ImageDraw
from skimage.io._plugins.pil_plugin import pil_to_ndarray
Expand Down Expand Up @@ -157,7 +157,7 @@ def audio_save(audio_or_file, filename, verbose=False, **kwargs):

def audio_modification(audio, loop_duration=None, volumex=1.,
fadein=False, fadeout=False, t_start=0, t_end=None,
speed=1.):
speed=1., keep_duration=False, wav=False):
"""
Modifies a sound.
Modifie un son.
Expand All @@ -170,17 +170,21 @@ def audio_modification(audio, loop_duration=None, volumex=1.,
@param t_start shorten the audio
@param t_end shorten the audio
@param speed speed of the sound
@param keep_duration parameter to
`ft_time <https://zulko.github.io/moviepy/ref/AudioClip.html?highlight=fl_time#moviepy.audio.AudioClip.AudioClip.fl_time>`_
@return new sound
"""
with AudioContext(audio) as audio:
if speed:
audio = audio.fl_time(lambda t: t * speed, keep_duration=True)
# wav = audio.to_soundarray(fps=audio.fps)
# audio = AudioArrayClip(wav, audio.fps)
if volumex != 1.:
audio = audio.fx(afx.volumex, volumex)
if loop_duration:
if audio.duration is None:
raise ValueError(
"The duration is unknown, maybe you should apply the loop first.")
audio = afx.audio_loop(audio, duration=loop_duration)
if volumex != 1.:
audio = audio.fx(afx.volumex, volumex)
if speed != 1.:
audio = audio.fl_time(lambda t: t * speed,
keep_duration=keep_duration)
if fadein:
audio = audio.fx(afx.audio_fadein, 1.0)
if fadeout:
Expand All @@ -190,6 +194,27 @@ def audio_modification(audio, loop_duration=None, volumex=1.,
return audio


def audio2wav(audio, duration=None, **kwargs):
"""
The sound is converted into :epkg:`wav`
and returned as an :epkg:`AudioArrayClip`.
Le son est converti au format :epkg:`wav`.
@param audio sound
@param duration change the duration of the sound before converting it
@param kwargs see `to_soundarray <https://zulko.github.io/moviepy/ref/AudioClip.html?highlight=to_soundarray#moviepy.audio.AudioClip.AudioClip.to_soundarray>`_
@return :epkg:`AudioArrayClip`
"""
with AudioContext(audio) as audio:
if duration is not None:
audio = audio.set_duration(duration)
wav = audio.to_soundarray(**kwargs)
fps = kwargs.get('fps', audio.fps if hasattr(audio, 'fps') else None)
if fps is None:
raise ValueError("fps cannot be None, 44100 is a proper value")
return AudioArrayClip(wav, fps=fps)


def audio_compose(audio_or_file1, audio_or_file2, t1=0, t2=None):
"""
Concatenates or superposes two sounds.
Expand Down Expand Up @@ -358,14 +383,14 @@ def video_enumerate_frames(video_or_file, folder=None, fps=10, pattern='images_%
yield name


def video_replace_audio(video_or_file, new_sound, **kwargs):
def video_replace_audio(video_or_file, new_sound, loop=True):
"""
Replaces the sound of a video.
Remplace la bande-son d'une vidéo.
@param video_or_file string or :epkg:`VideoClip`
@param new_sound sound
@param kwargs see @see fn audio_modification
@param loop loop on the audio if not long enough
@return :epkg:`VideoClip`
The list of available transformations is at:
Expand All @@ -381,10 +406,13 @@ def video_replace_audio(video_or_file, new_sound, **kwargs):
vid = video_replace_sound('video.mp4', 'son.mp3', loop=True, volumex=5.5, t_end='00:00:05')
"""
with VideoContext(video_or_file) as video:
if 'loop' in kwargs:
kwargs['loop_duration'] = video.duration
del kwargs['loop']
audio = audio_modification(new_sound, **kwargs)
if loop:
if video.duration is None:
raise ValueError(
"The duration of the video is unknown, use audio_modification and loop=False")
audio = audio_modification(new_sound, loop_duration=video.duration)
else:
audio = new_sound
new_clip = video.set_audio(audio)
return new_clip

Expand Down

0 comments on commit 182021b

Please sign in to comment.