Permalink
Browse files

refactoring, add function video_compose, documentation

  • Loading branch information...
sdpython committed Dec 30, 2017
1 parent 3d8174e commit eda16c64d8a1b34b0c930d6719a2dfa8a15b54af
View
@@ -10,7 +10,8 @@ install:
- pip freeze
- pip freeze > pip_freeze.txt
script:
- { CMD: "python -X faulthandler -X showrefcount -u setup.py unittests", NAME: "UT" }
- { CMD: "python -X faulthandler -X showrefcount -u setup.py unittests -g ".*noenv.*", NAME: "UT" }
- { CMD: "python -X faulthandler -X showrefcount -u setup.py unittests -e ".*noenv.*", NAME: "UT_NOENV" }
- { 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:
@@ -4,6 +4,18 @@
Vidéos et Sons
==============
Cette série de fonctions sont des exemples d'utilisation du module
:epkg:`moviepy`. Celui-ci permet de faire du montage vidéo
en programmant avec :epkg:`Python`. C'est sans doute moins puissant
qu'un vrai logiciel de montage tel que :epkg:`ShotCut` ou :epkg:`OpenShot`.
La progrommation a néanmoins deux avantages. Elle permet de répéter
un traitement facilement pour construire une vidéo. Elle peut opérer
la même opération sur chaque image d'un image comme l'extraction
des personnages du film (voir :ref:`imagemarypoppinsrst`).
Il est parfois plus simple de programmer plutôt que d'apprendre
à se servir d'un logiciel qui propose une interface utilisateur
pas toujours intuitive.
.. contents::
:local:
@@ -12,19 +24,25 @@ Audio
.. autosignature:: code_beatrix.faq.faq_video.audio_compose
.. autosignature:: code_beatrix.faq.faq_video.audio_extract_audio
.. autosignature:: code_beatrix.faq.faq_video.audio_modification
.. autosignature:: code_beatrix.faq.faq_video.audio_save
Video
+++++
.. autosignature:: code_beatrix.faq.faq_video.video_compose
.. autosignature:: code_beatrix.faq.faq_video.video_extract_video
.. autosignature:: code_beatrix.faq.faq_video.video_enumerate_frames
.. autosignature:: code_beatrix.faq.faq_video.video_extract_audio
.. autosignature:: code_beatrix.faq.faq_video.video_extract_video
.. autosignature:: code_beatrix.faq.faq_video.video_replace_sound
.. autosignature:: code_beatrix.faq.faq_video.video_save
@@ -75,8 +75,11 @@
epkg_dictionary['AutioClip'] = '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'
epkg_dictionary['OpenShot'] = 'https://www.openshot.org/'
epkg_dictionary['pytube'] = 'https://github.com/nficano/pytube'
epkg_dictionary['SciTe'] = 'http://www.scintilla.org/SciTE.html'
epkg_dictionary['scratch'] = "https://scratch.mit.edu/"
epkg_dictionary['ShotCut'] = 'https://www.shotcut.org/'
epkg_dictionary['VideoClip'] = 'https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html'
epkg_dictionary['youtube'] = "https://www.youtube.com/"
@@ -1 +1,3 @@
cartoon11.wav - source: http://www.grsites.com/
cartoon011.wav - source: http://www.grsites.com/
cartoon026.wav - source: http://www.grsites.com/
Binary file not shown.
@@ -46,24 +46,37 @@
from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import get_temp_folder, ExtTestCase
from src.code_beatrix.faq.faq_video import audio_compose, audio_save
from src.code_beatrix.faq.faq_video import audio_compose, audio_save, audio_extract_audio
class TestAudio(ExtTestCase):
def test_extract_audio(self):
def test_compose_audio(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")
temp = get_temp_folder(__file__, "temp_audio")
temp = get_temp_folder(__file__, "temp_audio_compose")
aud = os.path.join(temp, '..', 'data', 'cartoon011.wav')
aud2 = audio_compose(aud, aud, 1, 3)
exp = os.path.join(temp, "courte_audio.wav")
audio_save(aud2, exp)
self.assertExists(exp)
def test_extract_audio(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")
temp = get_temp_folder(__file__, "temp_audio_extract")
aud = os.path.join(temp, '..', 'data', 'cartoon026.wav')
aud2 = audio_extract_audio(aud, '00:00:01', '00:00:02')
exp = os.path.join(temp, "courte_audio.wav")
audio_save(aud2, exp)
self.assertExists(exp)
if __name__ == "__main__":
unittest.main()
@@ -46,7 +46,7 @@
from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import get_temp_folder, ExtTestCase
from src.code_beatrix.faq.faq_video import video_save, video_extract_video
from src.code_beatrix.faq.faq_video import video_save, video_extract_video, video_compose
class TestVideo(ExtTestCase):
@@ -62,6 +62,21 @@ def test_extract_avideo(self):
exp = os.path.join(temp, "courte.mp4")
video_save(vid2, exp)
self.assertExists(exp)
exp = os.path.join(temp, "courte.gif")
video_save(vid2, exp)
self.assertExists(exp)
def test_compose_avideo(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")
temp = get_temp_folder(__file__, "temp_video_compose")
vid = os.path.join(temp, '..', 'data', 'videxa.mp4')
vid2 = video_compose(vid, vid, '00:00:01', '00:00:04')
exp = os.path.join(temp, "courte.mp4")
video_save(vid2, exp)
self.assertExists(exp)
if __name__ == "__main__":
@@ -10,6 +10,7 @@
from imageio import imsave
import moviepy.audio.fx.all as afx
from moviepy.audio.AudioClip import AudioArrayClip, CompositeAudioClip
from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip
from .moviepy_context import AudioContext, VideoContext
@@ -64,24 +65,50 @@ def video_extract_video(video_or_file, ta=0, tb=None):
return video.subclip(ta, tb)
def audio_extract_audio(audio_or_file, ta=0, tb=None):
"""
Extracts a part of an audio.
Extrait une partie du son.
Uses `subclip <https://zulko.github.io/moviepy/ref/AudioClip.html?highlight=audioclip#moviepy.audio.AudioClip.AudioClip.subclip>`_.
@param audio_or_file string or :epkg:`AudioClip`
@param ta beginning
@param tb end
@return :epkg:`VideoClip`
"""
with AudioContext(audio_or_file) as audio:
return audio.subclip(ta, tb)
def video_save(video_or_file, filename, verbose=False, **kwargs):
"""
Saves as a video.
Saves as a video or as a :epkg:`gif`.
Enregistre une vidéo dans un fichier.
Uses `write_videofile <https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=videofileclip#moviepy.video.io.VideoFileClip.VideoFileClip.write_videofile>`_.
@param video_or_file string or :epkg:`VideoClip`
@param verbose logging or not
@param kwargs see `write_videofile <https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=videofileclip#moviepy.video.io.VideoFileClip.VideoFileClip.write_videofile>`_
"""
with VideoContext(video_or_file) as video:
if verbose:
video.write_videofile(filename, verbose=verbose, **kwargs)
else:
f = io.StringIO()
with redirect_stdout(f):
with redirect_stderr(f):
video.write_videofile(filename, verbose=verbose, **kwargs)
if isinstance(filename, str) and os.path.splitext(filename)[-1] == '.gif':
with VideoContext(video_or_file) as video:
if verbose:
video.write_gif(filename, verbose=verbose, **kwargs)
else:
f = io.StringIO()
with redirect_stdout(f):
with redirect_stderr(f):
video.write_gif(filename, verbose=verbose, **kwargs)
else:
with VideoContext(video_or_file) as video:
if verbose:
video.write_videofile(filename, verbose=verbose, **kwargs)
else:
f = io.StringIO()
with redirect_stdout(f):
with redirect_stderr(f):
video.write_videofile(
filename, verbose=verbose, **kwargs)
def audio_save(audio_or_file, filename, verbose=False, **kwargs):
@@ -212,7 +239,6 @@ def audio_compose(audio_or_file1, audio_or_file2, t1=0, t2=None):
@param audio_or_file2 son 2
@param t1 start of the first sound
@param t2 start of the second sound (or None to add it ad
@param concatenate concatenate or superpose
@return new sound
"""
with AudioContext(audio_or_file1) as audio1:
@@ -227,3 +253,30 @@ def audio_compose(audio_or_file1, audio_or_file2, t1=0, t2=None):
else:
add.append(audio2.set_start(t2))
return CompositeAudioClip(add)
def video_compose(video_or_file1, video_or_file2, t1=0, t2=None, **kwargs):
"""
Concatenates or superposes two videos.
Ajoute ou superpose deux vidéos.
@param video_or_file1 vidéo 1
@param video_or_file2 vidéo 2
@param t1 start of the first sound
@param t2 start of the second sound (or None to add it ad
@param kwargs additional parameters,
sent to `CompositeVideoClip <https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=compositevideoclip#compositevideoclip>`_
@return new sound
"""
with VideoContext(video_or_file1) as video1:
with VideoContext(video_or_file2) as video2:
add = []
if t1 != 0:
add.append(video1.set_start(t1))
else:
add.append(video1)
if t2 is None:
add.append(video2.set_start(video1.duration + t1))
else:
add.append(video2.set_start(t2))
return CompositeVideoClip(add)

0 comments on commit eda16c6

Please sign in to comment.