diff --git a/tests/test_main.py b/tests/test_main.py index 8961edd..6629f65 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -19,7 +19,6 @@ def generator(): return generator() return _black_generator - @pytest.mark.parametrize("fps,n_frames,n_channels", [(30, 60, 1), (30, 65, 3)]) def test_make_video(black_generator, tmpdir, fps, n_frames, n_channels): output_file = os.path.join(tmpdir, "output_vid.mp4") @@ -52,3 +51,43 @@ def test_make_video(black_generator, tmpdir, fps, n_frames, n_channels): def test_ffmpeg(tmpdir): output = os.path.join(tmpdir, "video.mp4") utils_video.ffmpeg(f"-f lavfi -i testsrc=duration=10:size=1280x720:rate=30 {output}") +""" +def test_handbrake(tmpdir): + def bar_generator(width=100, height=50, n_frames=502, n_channels=1): + w1 = width // 3 + w2 = width - 2*w1 + def generator(): + for i in range(n_frames): + frame = np.concatenate( + ( + np.zeros((height, w1, n_channels), dtype=np.uint8), + 255*np.ones((height, w2, n_channels), dtype=np.uint8), + np.zeros((height, w1, n_channels), dtype=np.uint8) + ), axis=1, dtype=np.uint8) + yield frame + return generator() + + output_file_fullsize = os.path.join(tmpdir, "output_vid_full.mp4") + print(f"=========={output_file_fullsize}==========") + generator = bar_generator() # (100, 50, n_frames, n_channels) + utils_video.make_video(output_file_fullsize, generator, 30, use_handbrake=False) + full_size = os.path.getsize(output_file_fullsize) + + # test handbrake inside make_video + output_file_redsize = os.path.join(tmpdir, "output_vid_red.mp4") + generator = bar_generator() # (100, 50, n_frames, n_channels) + utils_video.make_video(output_file_redsize, generator, 30, use_handbrake=True) + + # test handbrake on its own + output_file_redsize2 = os.path.join(tmpdir, "output_vid_red2.mp4") + utils_video.handbrake(video_path=output_file_fullsize, output_path=output_file_redsize2) + + assert os.path.isfile(output_file_redsize) + red_size = os.path.getsize(output_file_redsize) + assert red_size < full_size + assert os.path.isfile(output_file_redsize2) + red2_size = os.path.getsize(output_file_redsize2) + assert red2_size < full_size +""" + + diff --git a/utils_video/main.py b/utils_video/main.py index 333eccb..af9ce68 100644 --- a/utils_video/main.py +++ b/utils_video/main.py @@ -1,5 +1,6 @@ import itertools import subprocess +import os import cv2 from tqdm import tqdm @@ -7,7 +8,7 @@ from .utils import resize_shape -def make_video(video_path, frame_generator, fps, output_shape=(-1, 2880), n_frames=-1): +def make_video(video_path, frame_generator, fps, output_shape=(-1, 2880), n_frames=-1, use_handbrake=False): """ This function writes a video to file with all frames that the `frame_generator` yields. @@ -20,6 +21,8 @@ def make_video(video_path, frame_generator, fps, output_shape=(-1, 2880), n_fram Generator yielding individual frames. fps : int Frame rate in frames per second. + use_handbrake : bool + If true, attempt to use handbrake to compress the video. Default: False """ if float(fps).is_integer() and int(fps) != 1 and (int(fps) & (int(fps) - 1)) == 0: import warnings @@ -42,6 +45,8 @@ def make_video(video_path, frame_generator, fps, output_shape=(-1, 2880), n_fram video_writer.release() + if use_handbrake: + handbrake(video_path) def ffmpeg(command, pixel_format="yuv420p"): """ @@ -63,3 +68,49 @@ def ffmpeg(command, pixel_format="yuv420p"): command_list[:-1] + ["-pix_fmt", pixel_format] + [command_list[-1],] ) subprocess.run(["ffmpeg",] + command_list, check=True) + +def handbrake(video_path, output_path=None): + """apply HandBrake to a video to compress it. + This is an EXPERIMENTAL FEATURE and requires that the Handbrake command line + interface is installed! + + For installation follow the following steps: + Download the command line interface (CLI) from here: + https://handbrake.fr/downloads2.php + using the following instructions: + https://handbrake.fr/docs/en/1.5.0/get-handbrake/download-and-install.html + >>> flatpak --user install HandBrakeCLI-1.4.2-x86_64.flatpak + You might have to install flatpak with apt-get first. + If error about unacceptable TLS certificate pops up: + >>> sudo apt install --reinstall ca-certificates + Add flatpak to your PATH. This way you can use the commands below + >>> export PATH=$PATH:$HOME/.local/share/flatpak/exports/bin:/var/lib/flatpak/exports/bin + Now the CLI can be run as follows: + https://handbrake.fr/docs/en/latest/cli/cli-options.html + >>> fr.handbrake.HandBrakeCLI -i source -o destination + + Parameters + ---------- + video_path : str + path to your .mp4 video file + output_path : str, optional + where the compressed video should be saved to. If None, overwrite original video, by default None + """ + if output_path is None: + REPLACE = True + folder, file_name = os.path.split(video_path) + output_path = os.path.join(folder, "tmp_" + file_name) + else: + REPLACE = False + + export_path = "export PATH=$PATH:$HOME/.local/share/flatpak/exports/bin:/var/lib/flatpak/exports/bin" + # check whether handbrake CLI is installed + if os.system(export_path+" && fr.handbrake.HandBrakeCLI -h >/dev/null 2>&1"): + print("HandBrakeCLI is not installed.\n", + "Install files can be found here: https://handbrake.fr/downloads2.php \n", + "Install instructions here: https://handbrake.fr/docs/en/1.5.0/get-handbrake/download-and-install.html") + return + # run the client on the video + os.system(export_path+f" && fr.handbrake.HandBrakeCLI -i {video_path} -o {output_path}") + if REPLACE: + os.system(f"mv {output_path} {video_path}") \ No newline at end of file diff --git a/utils_video/utils.py b/utils_video/utils.py index 83fbfa6..79cf344 100644 --- a/utils_video/utils.py +++ b/utils_video/utils.py @@ -9,7 +9,7 @@ #from pandas.plotting._tools import _subplots, _flatten -import deepfly.plot_util +# import deepfly.plot_util dpi = 100 img3d_aspect = (2, 2) @@ -265,6 +265,7 @@ def natsorted(list_of_strs): def plot_df3d_pose(points3d): + """ plt.style.use("dark_background") fig = plt.figure(figsize=img3d_aspect, dpi=dpi) fig.tight_layout(pad=0) @@ -281,6 +282,8 @@ def plot_df3d_pose(points3d): data = fig_to_array(fig) plt.close() return data + """ + return None def roi_image(background, mask, connectivity=4, min_size=0, cm="autumn"):