Skip to content

Commit

Permalink
added parameter place to video compose, documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sdpython committed Jan 10, 2018
1 parent 6f49a66 commit fa09b38
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 28 deletions.
74 changes: 74 additions & 0 deletions _unittests/ut_faq/test_video_noenv4_placement.py
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""
@brief test log(time=1000s)
Duraction is around a few seconds but the test needs to be run
at the end of the series of unitests as it interferes
with the notebook unittesting (it uses Popen too).
"""


import sys
import os
import unittest


try:
import pyquickhelper
except ImportError:
path = os.path.normpath(
os.path.abspath(
os.path.join(
os.path.split(__file__)[0],
"..",
"..",
"..",
"pyquickhelper",
"src")))
if path not in sys.path:
sys.path.append(path)
import pyquickhelper


try:
import src
except ImportError:
path = os.path.normpath(
os.path.abspath(
os.path.join(
os.path.split(__file__)[0],
"..",
"..")))
if path not in sys.path:
sys.path.append(path)
import src


from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import get_temp_folder, ExtTestCase
from src.code_beatrix.faq.faq_video import video_save, video_compose


class TestVideoPlacement(ExtTestCase):

def test_modify_placement(self):
fLOG(
__file__,
self._testMethodName,
OutputPrint=__name__ == "__main__")
temp = get_temp_folder(__file__, "temp_video_placement")
vid = os.path.join(temp, '..', 'data', 'videxa.mp4')

vid2 = video_compose(vid, vid, t2=1, place='h2')
exp = os.path.join(temp, "h2.mp4")
video_save(vid2, exp)
self.assertExists(exp)

vid2 = video_compose(vid, vid, t2=1, place='v2')
exp = os.path.join(temp, "v2.mp4")
video_save(vid2, exp)
self.assertExists(exp)


if __name__ == "__main__":
unittest.main()
110 changes: 82 additions & 28 deletions src/code_beatrix/faq/faq_video.py
Expand Up @@ -374,7 +374,7 @@ def video_remove_audio(video_or_file):
return video.without_audio()


def video_compose(video_or_file1, video_or_file2=None, t1=0, t2=0, **kwargs):
def video_compose(video_or_file1, video_or_file2=None, t1=0, t2=0, place=None, **kwargs):
"""
Concatenates or superposes two videos.
Ajoute ou superpose deux vidéos.
Expand All @@ -383,6 +383,7 @@ def video_compose(video_or_file1, video_or_file2=None, t1=0, t2=0, **kwargs):
@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 place predefined placements
@param kwargs additional parameters,
sent to `CompositeVideoClip <https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html?highlight=compositevideoclip#compositevideoclip>`_
@return :epkg:`VideoClip`
Expand All @@ -395,35 +396,88 @@ def video_compose(video_or_file1, video_or_file2=None, t1=0, t2=0, **kwargs):
vid = video_compose('video1.mp4', 'video2.mp4', '00:00:01', '00:00:04')
The first video defines the size of the final video.
List of predefined placements:
* *h2*: two videos side by side horizontally
* *v2*: two videos side by side vertically
"""
if isinstance(video_or_file1, list):
if video_or_file2 is not None:
raise ValueError(
'video_or_file1 is a list, video_or_file2 should be None')
vids = [VideoContext(i).__enter__() for i in video_or_file1]
comp = []
for i, v in enumerate(vids):
v = v.video
if isinstance(t1, list) and i < len(t1):
v.set_start(t1[i])
comp.append(v)
res = CompositeVideoClip(comp, **kwargs)
for v in vids:
v.__exit__()
return res
if place is None:
if isinstance(video_or_file1, list):
if video_or_file2 is not None:
raise ValueError(
'video_or_file1 is a list, video_or_file2 should be None')
vids = [VideoContext(i).__enter__() for i in video_or_file1]
comp = []
for i, v in enumerate(vids):
v = v.video
if isinstance(t1, list) and i < len(t1):
v.set_start(t1[i])
comp.append(v)
res = CompositeVideoClip(comp, **kwargs)
for v in vids:
v.__exit__()
return res
else:
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, **kwargs)
else:
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, **kwargs)

def get_two(video_or_file1, video_or_file2, t1, t2):
if isinstance(video_or_file1, list):
if len(video_or_file1) != 2:
raise ValueError(
"Expecting two videos not {0}".format(len(video_or_file1)))
v1, v2 = video_or_file1
t1, t2 = t1
else:
if len(video_or_file2) is None:
raise ValueError("Expecting two videos not less")
v1, v2 = video_or_file1, video_or_file2
vc1 = VideoContext(v1).__enter__()
vc2 = VideoContext(v2).__enter__()
return (vc1, vc2), (t1, t2)

(vc1, vc2), (t1, t2) = get_two(video_or_file1, video_or_file2, t1, t2)
v1 = vc1.video
v2 = vc2.video

# Predefined placements.
if place == "h2":
pos1 = 0, 0
pos2 = v1.size[0], 0
v1 = video_position(v1, pos=pos1)
v2 = video_position(v2, pos=pos2)
if 'size' not in kwargs:
kwargs['size'] = v1.size[0] + \
v2.size[0], max(v1.size[1], v2.size[1])
res = video_compose(v1, v2, t1, t2, **kwargs)
elif place == "v2":
(vc1, vc2), (t1, t2) = get_two(
video_or_file1, video_or_file2, t1, t2)
pos1 = 0, 0
pos2 = 0, v1.size[1]
v1 = video_position(v1, pos=pos1)
v2 = video_position(v2, pos=pos2)
if 'size' not in kwargs:
kwargs['size'] = max(v1.size[0], v2.size[0]
), v1.size[1] + v2.size[1]
res = video_compose(v1, v2, t1, t2, **kwargs)
else:
raise ValueError("Unknown placement '{0}'".format(place))

vc1.__exit__()
vc2.__exit__()
return res


def video_concatenate(video_or_files, **kwargs):
Expand Down

0 comments on commit fa09b38

Please sign in to comment.