Skip to content

Commit

Permalink
unit test and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sdpython committed Jan 2, 2018
1 parent abfeb61 commit 5c7ea68
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 5 deletions.
36 changes: 34 additions & 2 deletions _doc/sphinxdoc/source/api/video.rst
Expand Up @@ -14,16 +14,46 @@ 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.
pas toujours intuitive (lire aussi
:ref:`Montage vidéo avec Python <b-montage-video-2018>`.

.. contents::
:local:

Les fonctions sur les vidéos commencent quasiment toutes par le même
paramètre :*video_or_file*. Celui-ci peut soit être un nom de fichier,
soit un objet de type :epkg:`VideoClip`. Un exemple :

::

from code_beatrix.faq.faq_video import video_concatenate, video_save

new_video = video_concatenate(["video1.mp4", "video2.avi"])
video_save(new_video)

Un autre exemple où la première vidéo est un extrait d'une vidéo :

::

from code_beatrix.faq.faq_video import video_concatenate, video_save

v1 = video_extract_video("video1.mp4", '00:00:01.45', '00:00:010.51')
new_video = video_concatenate([v1, "video2.avi"])
video_save(new_video)

La même logique s'applique aux sons. Les fonctions qui suivent
couvrent un petit sous-ensemble de ce qu'il est possible de faire
avec le module :epkg:`moviepy`. Pour aller plus loin, il peut être
utile de s'inspirer du code de celles-ci et de regarder
les `exemples de la documentation <https://zulko.github.io/moviepy/examples/examples.html>`_.

Audio
+++++

.. autosignature:: code_beatrix.faq.faq_video.audio_compose

.. autosignature:: code_beatrix.faq.faq_video.audio_concatenate

.. autosignature:: code_beatrix.faq.faq_video.audio_extract_audio

.. autosignature:: code_beatrix.faq.faq_video.audio_modification
Expand All @@ -35,14 +65,16 @@ 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_concatenate

.. 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_modification

.. autosignature:: code_beatrix.faq.faq_video.video_replace_sound

.. autosignature:: code_beatrix.faq.faq_video.video_save
Expand Down
@@ -0,0 +1,66 @@

.. blogpost::
:title: Montage vidéo avec Python
:keywords: montage, audio, sons, film, youtube
:date: 2018-01-02
:categories: video
:lid: b-montage-video-2018

Je me suis mis en tête d'initier des adolescents à la
programmation en faisant du montage vidéo. Il est facile
aujourd'hui de se filmer avec un téléphone portable ou une
tablette mais il faut pouvoir retravailler les prises
et les assembler si on souhaite réaliser un petit film.
La programmation n'est sans doute le premier réflexe et je
me doute que beaucoup iront chercher sur internet un logiciel
permettant de faire cela. Cela veut dire aussi un certain
coût d'apprentissage. Je n'ai pas essayé même si j'ai trouvé
un logiciel tel que :epkg:`ShotCut`
(voir `FramaLibre / montage <https://framalibre.org/recherche-par-crit-res?keys=montage>`_).
Au lieu de ça, j'ai regardé s'il existait un module :epkg:`Python`
qui me permettait de faire cela. J'ai trouvé
:epgk:`moviepy` et surtout la
`gallerie d'exemples <https://zulko.github.io/moviepy/examples/examples.html>`_
qui donne une assez bonne idée de ce qu'on peut faire avec.

Cette approche est plus coûteuse lorsqu'il s'agit de faire des opérations
simples tels que mettre bout à bout ou extraire un extrait d'une vidéo
puisque que l'outil qui permet de visualiser le résultat
(comme :epkg:`VLC`) est différent de celui qu'on utilise pour
construire ce qu'on peut (:epkg:`Python` dans mon cas).
Néanmoins, cette approche est moins coûteuse lorsqu'il s'agit
de faire un traitement complexe comme parcourir un film image
par image, extraire les personnages et les insérer dans une autre
vidéo. J'ai par exemple isolé
:epkg:`Mary Poppins` du décor dans lequel elle danse.

.. image:: images/image_mary_poppins_12_0.jpeg

Ce procédé s'appuie sur du :epkg:`deep learning` et je ne pense pas
que cette fonctionnalité soit accessible depuis un logiciel de
montage vidéo. Et si jamais ça l'était, cela serait sans doute via
une interface utilisateur plutôt complexe. Et voici
:epkg:`Mary Poppins` sur une plage.

.. image:: images/image_mary_poppins_29_1.png

Ce qu'on souhaite faire est souvent un assemblage plus ou moins
long de tâche simple et c'est assez facile à écrire qu'on on dispose
d'un moyen d'enchaîner ces tâches simples. Le résultat est
parfois complexe et si l'interface utilisateur existait, elle ferait
apparaître de nombreuses options qui feraient probablement un peu
peur au premier regard. C'est mon expérience, je ne dis pas que ce
soit la seule, mais je pense qu'on passe moins de temps à explorer
toutes les options ou contourner les limites de l'outil
qu'on utilise en passant directement par
la programmation plutôt que par un logiciel tout fait.
Cela se traduit néanmoins par une approche un peu plus abstraite.
A l'usage, on se sert des deux outils.

Pour préparer ce travail, j'ai cherché à écrire un peu de lignes
une façon de récupérer une vidéo, d'en extrait un bout,
d'y ajouter une bande son, quelques incrustations textuelles.
Cela m'a permis de constituer une petite liste de fonctions
dont on peut s'inspirer : :ref:`l-api-video-audio` et quelques jeux
:ref:`l-medias`. Quelques notebooks qui pourraient vous intéresser :
:ref:`imagemarypoppinsrst`, :ref:`imagesegmentationrst`.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions _doc/sphinxdoc/source/conf.py
Expand Up @@ -76,10 +76,14 @@
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[
'Mary Poppins'] = 'https://fr.wikipedia.org/wiki/Mary_Poppins_(film,_1964)'
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['VLC'] = 'https://www.videolan.org/vlc/index.html'
epkg_dictionary['YouTube'] = "https://www.youtube.com/"
epkg_dictionary['youtube'] = "https://www.youtube.com/"
1 change: 1 addition & 0 deletions _doc/sphinxdoc/source/index.rst
Expand Up @@ -45,6 +45,7 @@ Contenu rangé par thèmes
arduino/index_arduino
histoires/index_histoires
maths/index_maths
medias/index_medias
API/index

On programme pour faire des jeux, des sites internets, des recherches scientifiques,
Expand Down
45 changes: 45 additions & 0 deletions _doc/sphinxdoc/source/media/index_media.rst
@@ -0,0 +1,45 @@

.. _l-medias:

Médias
======

Le monde d'aujourd'hui est à mon grand regret très médiatique.
Les enfants lisent moins, ingurgitent des vidéos sur :epkg:`YouTube` et
ce média a à mon avis l'inconvénient de réduire l'interprétation
d'une même histoire. Le texte laisse au lecteur le soin d'imaginer
un décor, une musique issus de sa propre expérience. Une vidéo
propose déjà une forme, un rendu dont il est difficile de se défaire.

Mais ainsi soit-il... Puisque c'est ludique, essayons au moins
d'en être les auteurs. Essayons d'imaginer quelques jeux autour
de cela orientés à n'en pas douter vers la programmation, choix que
je détaille un peu plus dans cet article :
:ref:`Montage vidéo avec Python <b-montage-video-2018>`.

Sujets
------

.. toctree::
:maxdepth: 1

montage_video

Indices et solutions
--------------------

.. toctree::
:maxdepth: 1

montage_video_correction

.. _l-biblio_prog:

Bibliographie
-------------

Modules Python
--------------

* :epkg:`moviepy`
* :epkg:`pytube`
88 changes: 88 additions & 0 deletions _doc/sphinxdoc/source/media/montage_video.rst
@@ -0,0 +1,88 @@

.. index:: énoncé, vidéo, montage

.. _l-montage_video:

Petit montage vidéo avec Python
===============================

A partir de 7 ans.

L'objectif de l'exercice est d'assembler des bouts de vidéos
existantes, qu'elles viennent de son téléphone ou de :epkg:`youtube`,
de changer la bande son, d'ajouter des inscrustations.
Si les exercices suivants peuvent être réalisés
avec :epkg:`moviepy`, des fonctions ont été implémentées
pour résoudre les exercices et sont décrites ici :
:ref:`l-api-video-audio`. Il ne s'agit pas d'écrire des programmes
compliqués mais plutôt de passer le plus de temps possible
sur la réalisation de petits films.

Mise en scène
-------------

On souhaite réaliser un dialogue imaginaire à partir de
personnages qui appartiennent à des films ou à des vidéos
différentes.

Exercice 1
----------

#. Ecrire un petit scénario avec deux ou trois répliques
qu'on pourra réaliser à partir de vidéos :epkg:`youtube`.
On peut choisir des films, des chansons...
#. Télécharger les vidéos si besoin avec le module
:epkg:`pytube` ou la fonction
:func:`download_youtube_video <code_beatrix.faq.faq_video.download_youtube_video>`.
#. Visionner les vidéos et noter à la seconde près les extraits
des vidéos.
#. Extraire chaque bout avec la fonction
:func:`video_extract_video <code_beatrix.faq.faq_video.video_extract_video>`.
#. Assembler chaque bout en une seule vidéo avec la fonction
:func:`video_concatenate <code_beatrix.faq.faq_video.video_concatenate>`.
#. Enregister la vidéo avec la fonction
:func:`video_save <code_beatrix.faq.faq_video.video_save>`.

Exercice 2
----------

#. On reprend la vidéo précédente et on y inscrute
du texte et des images pour commenter ce que les personnages,
pour s'en moquer ou font ou pour les doubler.
**fonction non implémentée**
#. Enregister la vidéo avec la fonction
:func:`video_save <code_beatrix.faq.faq_video.video_save>`.

Exercice 3
----------

#. Extraire la bande de la vidéo précédente avec la fonction
:func:`video_extract_audio <code_beatrix.faq.faq_video.video_extract_audio>`.
#. Choisir une musique pour en faire une bande son.
#. Superposer les deux sons avec la fonction
:func:`audio_compose <code_beatrix.faq.faq_video.audio_compose>`.
#. Enregister la vidéo avec la fonction
:func:`video_save <code_beatrix.faq.faq_video.video_save>`.

Exercice 4
----------

On reprend toutes les opérations pour un faire une seul programme
qu'on exécute pour vérifier qu'il donne bien la même chose qu'avant.
On choisit un des personnages et le faire parler deux plus vite
avec la fonction
:func:`video_modification <code_beatrix.faq.faq_video.video_modification>`.

Solution
--------

Voir :ref:`l-montage_video_sol`.

A quoi ça sert ?
----------------

Démarrer sa propre chaîne :epkg:`youtube` et devenir
un célèbre *youtubeur* ou
`Vidéaste (web) <https://fr.wikipedia.org/wiki/Vid%C3%A9aste_(Web)>`_
et avoir sa propre chaîne comme
`Science Etonnante <https://www.youtube.com/channel/UCaNlbnghtwlsGF-KzAFThqA>`_.
21 changes: 21 additions & 0 deletions _doc/sphinxdoc/source/media/montage_video_correction.rst
@@ -0,0 +1,21 @@

.. index:: solution, vidéo, montage

.. _l-montage_video_sol:

Petit montage vidéo avec Python (solution)
==========================================

Solution de :ref:`l-montage_video`.

Exercice 1
----------

Exercice 2
----------

Exercice 3
----------

Exercice 4
----------
7 changes: 6 additions & 1 deletion _unittests/ut_faq/test_audio_noenv1.py
Expand Up @@ -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 audio_compose, audio_save, audio_extract_audio
from src.code_beatrix.faq.faq_video import audio_compose, audio_save, audio_extract_audio, audio_concatenate


class TestAudio(ExtTestCase):
Expand All @@ -64,6 +64,11 @@ def test_compose_audio(self):
audio_save(aud2, exp)
self.assertExists(exp)

aud3 = audio_concatenate([aud, aud])
exp = os.path.join(temp, "courte_audio2.wav")
audio_save(aud3, exp)
self.assertExists(exp)

def test_extract_audio(self):
fLOG(
__file__,
Expand Down
7 changes: 6 additions & 1 deletion _unittests/ut_faq/test_video_noenv1.py
Expand Up @@ -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, video_compose
from src.code_beatrix.faq.faq_video import video_save, video_extract_video, video_compose, video_concatenate


class TestVideo(ExtTestCase):
Expand Down Expand Up @@ -78,6 +78,11 @@ def test_compose_avideo(self):
video_save(vid2, exp)
self.assertExists(exp)

exp = os.path.join(temp, "courte2.mp4")
vid3 = video_concatenate([vid, vid])
video_save(vid3, exp)
self.assertExists(exp)


if __name__ == "__main__":
unittest.main()

0 comments on commit 5c7ea68

Please sign in to comment.