Docker基础知识 (17) - 使用 Docker 部署 Python + OpenCV-Python/Moviepy 编辑图像和视频


Python 是一种由 Guido van Rossum 开发的通用编程语言,它很快就变得非常流行,主要是因为它的简单性和代码可读性。它使程序员能够用更少的代码行表达思想,而不会降低可读性。

Python 可以轻松使用 C/C++ 扩展,这使我们可以在 C/C++ 中编写计算密集型代码,并创建可用作 Python 模块的 Python 包装器。这给我们带来了两个好处:首先,代码与原始 C/C++ 代码一样快(因为它在后台工作的实际 c/C++ 代码),其次,在 Python 中编写代码比使用 C/C++ 更容易。

Python: https://www.python.org/

OpenCV

OpenCV(Open Source Computer Vision)由英特尔公司于 1999 年推出,如今由 Willow Garage 提供支持。它是一个基于 BSD 许可(开源)发行的跨平台计算机视觉库,可以运行在 Linux、Windows、MacOS 操作系统上。

OpenCV 轻量级而且高效,由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、Ruby、MATLAB 等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法,它在 Python 中也被广泛用于计算机视觉。

简言之,通过 OpenCV 可实现计算机图像、视频的编辑。广泛应用于图像识别、运动跟踪、机器视觉等领域。

OpenCV: https://opencv.org/
OpenCV GitHub: https://github.com/opencv


OpenCV-Python

OpenCV-Python 是一个 Python 库/包,旨在解决计算机视觉问题。OpenCV-Python 是原始 OpenCV C/C++ 实现的 Python 库/包。

OpenCV-Python 使用 Numpy,这是一个高度优化的数据库操作库,具有 MATLAB 风格的语法。所有 OpenCV 数组结构都转换为 Numpy 数组。这也使得与使用 Numpy 的其他库(如 SciPy 和 Matplotlib )集成更容易。

OpenCV-Python: https://pypi.org/project/opencv-python

 

MoviePy

MoviePy 是一个用于视频编辑的 Python 模块,可用于进行视频的基本操作(如剪切、连接、标题插入)、视频合成(也称非线性编辑)、视频处理或创建高级效果。


MoviePy 能处理的视频是 ffmpeg 格式的,支持的文件类型:*.mp4 *.wmv *.rm *.avi *.flv *.webm *.wav *rmvb 。

MoviePy: https://pypi.org/project/moviepy/
Github: https://github.com/Zulko/moviepy

注:Moviepy 是一个 Python 的音视频剪辑库,OpenCV 是一个图形处理库,视频的一帧就是一幅图像,因此在处理视频时可以结合 OpenCV 进行帧处理,将二者结合可以用来进行视频特效的处理。


1. 部署环境

    IP 地址(本地测试环境):192.168.0.10
    操作系统:Linux CentOS 7.9     
    Docker 版本: 20.10.7
    Docker Compose 版本: 2.6.1
    OpenCV-Python 版本:3.4.8.29

    工作目录:/home/docker/python_media


2. 创建 Dockerfile

    $ cd /home/docker/python_media
    $ vim Dockerfile

        FROM python:3.8
        WORKDIR /home/docker/python_media/work
        #COPY . /home/docker/python_media/work
        RUN pip install -i https://mirrors.aliyun.com/pypi/simple opencv-python==3.4.8.29
        RUN pip install -i https://mirrors.aliyun.com/pypi/simple moviepy==1.0.3

 


3. 创建 python_media 镜像

    $ cd /home/docker/python_media

    $ docker build -t python_media:3.8 .

        Sending build context to Docker daemon  9.216kB
        Step 1/4 : FROM python:3.8
        ---> 5e51aed29a27
        Step 2/4 : WORKDIR /home/docker/python_media
        ---> Running in bfa5952eec12
        Removing intermediate container bfa5952eec12
        ---> 536afc6d0b85
        Step 3/4 : RUN pip install -i https://mirrors.aliyun.com/pypi/simple opencv-python==3.4.8.29
        ---> Running in 4238ef77d8e2
        Looking in indexes: https://mirrors.aliyun.com/pypi/simple
        Collecting opencv-python==3.4.8.29
        Downloading https://mirrors.aliyun.com/pypi/packages/bd/95/f06beabb5e1fa319f02278004efce19e7ebe7a67e69dd7d1820d64b2dab8/opencv_python-3.4.8.29-cp38-cp38-manylinux1_x86_64.whl (28.3 MB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 28.3/28.3 MB 261.3 kB/s eta 0:00:00
        Collecting numpy>=1.17.3
        Downloading https://mirrors.aliyun.com/pypi/packages/56/df/2f6016171ebce9875e7de0292a2131bea86e0340607a313a04b332d35c8e/numpy-1.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (17.1 MB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 17.1/17.1 MB 257.3 kB/s eta 0:00:00
        Installing collected packages: numpy, opencv-python

        ...

        Step 4/4 : RUN pip install -i https://mirrors.aliyun.com/pypi/simple moviepy==1.0.3
        ---> Running in 4011b24e7bc4
        Looking in indexes: https://mirrors.aliyun.com/pypi/simple
        Collecting moviepy==1.0.3
        Downloading https://mirrors.aliyun.com/pypi/packages/18/54/01a8c4e35c75ca9724d19a7e4de9dc23f0ceb8769102c7de056113af61c3/moviepy-1.0.3.tar.gz (388 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 388.3/388.3 KB 201.0 kB/s eta 0:00:00
        Preparing metadata (setup.py): started
        Preparing metadata (setup.py): finished with status 'done'
        Collecting decorator<5.0,>=4.0.2
        Downloading https://mirrors.aliyun.com/pypi/packages/ed/1b/72a1821152d07cf1d8b6fce298aeb06a7eb90f4d6d41acec9861e7cc6df0/decorator-4.4.2-py2.py3-none-any.whl (9.2 kB)
        Collecting tqdm<5.0,>=4.11.2
        Downloading https://mirrors.aliyun.com/pypi/packages/47/bb/849011636c4da2e44f1253cd927cfb20ada4374d8b3a4e425416e84900cc/tqdm-4.64.1-py2.py3-none-any.whl (78 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.5/78.5 KB 200.4 kB/s eta 0:00:00
        Collecting requests<3.0,>=2.8.1
        Downloading https://mirrors.aliyun.com/pypi/packages/ca/91/6d9b8ccacd0412c08820f72cebaa4f0c0441b5cda699c90f618b6f8a1b42/requests-2.28.1-py3-none-any.whl (62 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.8/62.8 KB 189.6 kB/s eta 0:00:00
        Collecting proglog<=1.0.0
        Downloading https://mirrors.aliyun.com/pypi/packages/8b/f5/cab5cf6a540c31f5099043de0ae43990fd9cf66f75ecb5e9f254a4e4d4ee/proglog-0.1.10-py3-none-any.whl (6.1 kB)
        Requirement already satisfied: numpy>=1.17.3 in /usr/local/lib/python3.8/site-packages (from moviepy==1.0.3) (1.23.4)
        Collecting imageio<3.0,>=2.5
        Downloading https://mirrors.aliyun.com/pypi/packages/97/e2/c5bb16905ab91a0fac03f2a4f1579835bcfea3e297f8cf53e4e2b43c270c/imageio-2.22.2-py3-none-any.whl (3.4 MB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.4/3.4 MB 184.6 kB/s eta 0:00:00
        Collecting imageio_ffmpeg>=0.2.0
        Downloading https://mirrors.aliyun.com/pypi/packages/e5/3b/fdf3e75462e93b7806ffecad6c5aa35f2cc76b9f2faaedf5e43194ceff09/imageio_ffmpeg-0.4.7-py3-none-manylinux2010_x86_64.whl (26.9 MB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 26.9/26.9 MB 177.0 kB/s eta 0:00:00
        Collecting pillow>=8.3.2
        Downloading https://mirrors.aliyun.com/pypi/packages/d8/80/ff6b6ae88982f73d050907dc2c307f387f6a04ce2ca7230ef3a568fbccac/Pillow-9.2.0-cp38-cp38-manylinux_2_28_x86_64.whl (3.2 MB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.2/3.2 MB 180.3 kB/s eta 0:00:00
        Collecting idna<4,>=2.5
        Downloading https://mirrors.aliyun.com/pypi/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl (61 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.5/61.5 KB 158.4 kB/s eta 0:00:00
        Collecting urllib3<1.27,>=1.21.1
        Downloading https://mirrors.aliyun.com/pypi/packages/6f/de/5be2e3eed8426f871b170663333a0f627fc2924cc386cd41be065e7ea870/urllib3-1.26.12-py2.py3-none-any.whl (140 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 140.4/140.4 KB 194.1 kB/s eta 0:00:00
        Collecting certifi>=2017.4.17
        Downloading https://mirrors.aliyun.com/pypi/packages/1d/38/fa96a426e0c0e68aabc68e896584b83ad1eec779265a028e156ce509630e/certifi-2022.9.24-py3-none-any.whl (161 kB)
            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 161.1/161.1 KB 184.5 kB/s eta 0:00:00
        Collecting charset-normalizer<3,>=2
        Downloading https://mirrors.aliyun.com/pypi/packages/db/51/a507c856293ab05cdc1db77ff4bc1268ddd39f29e7dc4919aa497f0adbec/charset_normalizer-2.1.1-py3-none-any.whl (39 kB)
        Building wheels for collected packages: moviepy
        Building wheel for moviepy (setup.py): started
        Building wheel for moviepy (setup.py): finished with status 'done'
        Created wheel for moviepy: filename=moviepy-1.0.3-py3-none-any.whl size=110743 sha256=26a5092d88a9ce5490d3fe9177dfbb78aec86fcd55bb206de0d3d35d47a787de
        Stored in directory: /root/.cache/pip/wheels/fb/56/20/ea8039f0f19ff16db00131559d9290ff7cddf4711b64a3ff27
        Successfully built moviepy
        Installing collected packages: urllib3, tqdm, pillow, imageio_ffmpeg, idna, decorator, charset-normalizer, certifi, requests, proglog, imageio, moviepy
        Successfully installed certifi-2022.9.24 charset-normalizer-2.1.1 decorator-4.4.2 idna-3.4 imageio-2.22.2 imageio_ffmpeg-0.4.7 moviepy-1.0.3 pillow-9.2.0 proglog-0.1.10 requests-2.28.1 tqdm-4.64.1 urllib3-1.26.12


    $ docker images

        REPOSITORY         TAG              IMAGE ID       CREATED         SIZE
        python_media       3.8              755ea9005f1c   10 minutes ago  1.24GB
        python             3.8              5e51aed29a27   2 days ago      913MB


4. 创建 docker-compose.yml

    $ cd /home/docker/python_media
    $ vim docker-compose.yml

        version: "3"
        services:
            python_media:
                image: python_media:3.8
                container_name: python_media-3.8
                restart: always
                volumes:
                    - /home/docker/python_media/work:/home/docker/python_media/work              
                entrypoint: "sleep infinity"


    注:当容器启动后没有 service 运行,但又想继续保持 running 状态,可以添加 entrypoint: "tail -f /dev/null" (即查看空设备的日志,一直会处于阻塞状态),也可以使用 entrypoint: "sleep infinity" (睡眠阻塞)。


5. 启动

    $ cd /home/docker/python_media   # 进入 docker-compose.yml 所在目录

    $ docker-compose up -d   # 在后台运行

        [+] Running 2/2
        ⠿ Network python_opencv_default         Created                0.0s
        ⠿ Container python_media-3.8             Started                0.3s

    $ docker ps


        CONTAINER ID   IMAGE              COMMAND               PORTS     NAMES
        627ad779b82a   python_media:3.8   "sleep infinity"                python_media-3.8


6. Python 测试程序

    $ cd /home/docker/python_media/work
    $ mkdir scripts && cd scripts
    $ vim hello.py

        #!/usr/bin/python3
        # -*- coding: UTF-8 -*-

        print("Hello world - 你好!")

    $ docker exec -t python_media-3.8 python /home/docker/python_media/work/scripts/hello.py

        Hello world - 你好!


7. OpenCV 程序

    OpenCV 的几个基础模块:

        (1) core 模块: 实现了最核心的数据结构及其基本运算,如绘图函数、数组操作相关函数等;
        (2) highgui 模块:实现了视频与图像的读取、显示、存储等接口;
        (3) imgproc 模块:实现了图像处理的基础方法,包括图像滤波、图像的几何变换、平滑、阈值分割、形态学处理、边缘检测、目标检测、运动分析和对象跟踪等;

    图像处理其它应用的模块:
        
        (1) features2d 模块:用于提取图像特征以及特征匹配;
        (2) nonfree 模块:实现了一些专利算法,如 sift 特征;
        (3) objdetect 模块:实现了一些目标检测的功能,经典的基于 Haar、LBP 特征的人脸检测,基于 HOG 的行人、汽车等目标检测,分类器使用 Cascade Classification(级联分类)和 Latent SVM 等;
        (4) stitching 模块:实现了图像拼接功能;
        (5) FLANN(Fast Library for Approximate Nearest Neighbors)模块,包含快速近似最近邻搜索 FLANN 和聚类 Clustering 算法;
        (6) ml 模块:机器学习模块(SVM,决策树,Boosting 等);
        (7) photo 模块:包含图像修复和图像去噪两部分;
        (8) video 模块:针对视频处理,如背景分离,前景检测、对象跟踪等;
        (9) calib3d (即 Calibration 3D)模块:主要是相机校准和三维重建相关的内容。包含了基本的多视角几何算法,单个立体摄像头标定,物体姿态估计,立体相似性算法,3D 信息的重建等等;
        (10) G-API 模块:包含超高效的图像处理 pipeline 引擎。

    这里演示一个把长视频切割成固定时间的短视频的实例。

    1) 视频资源

        文件名:test.mp4
        文件大小:9.52 MB
        时长:14.93 秒
        视频源文件:/home/docker/python_media/work/res/test.mp4

    2) 创建脚本

        $ cd /home/docker/python_media/work/scripts
        $ vim opencv_split.py

  1             #!/usr/bin/python3
  2 
  3             import os, sys, time
  4             import os.path as osp
  5 
  6             import cv2
  7 
  8 
  9             # 默认值
 10             save_dir = '/out'
 11             default_seconds = 1
 12             max_count = 999
 13 
 14             def splitFile(filename, dura, sdir):
 15 
 16                 # Check parameters and file path
 17                 if filename.isspace() == True or dura < default_seconds or sdir.isspace == True:
 18                     print("Error: invalid parameters")
 19                     return
 20 
 21                 if osp.exists(filename) != True:
 22                     print(f"Error: \'{filename}\' not exists")
 23                     return
 24 
 25                 if osp.exists(sdir) != True:
 26                     os.mkdir(sdir)
 27 
 28                 # Open video file and get video parameters
 29                 print(f"Info: opening \'{filename}\' ...")
 30                 video_cap = cv2.VideoCapture(filename)
 31 
 32                 video_fps = int(video_cap.get(cv2.CAP_PROP_FPS))
 33                 video_frames = int(video_cap.get(cv2.CAP_PROP_FRAME_COUNT))
 34 
 35                 duration_end = float(format(video_frames/video_fps, '.2f'))
 36                 if duration_end <= dura:
 37                     print(f"Error: video duration {duration_end} seconds <= {dura} seconds, unable to split")
 38                     return
 39 
 40                 # Calculate split file count
 41                 filecount = int(duration_end // dura)
 42                 if (duration_end % dura) > 1.0:
 43                     filecount += 1
 44 
 45                 if filecount > max_count:
 46                     print(f"Error: file count {filecount} > {max_count}, unable to split")        
 47                     return
 48 
 49                 #
 50                 print(f"Info: split to {filecount} files ...")
 51 
 52                 frame_index = 1
 53                 file_index = 1
 54 
 55                 fileObj = osp.splitext(osp.basename(filename))
 56                 output_fullname = "{0}/{1}_{2:03d}{3}".format(sdir, fileObj[0], file_index, fileObj[1])
 57 
 58                 dura_frames = dura * video_fps
 59                 frame_size = (int(video_cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
 60 
 61                 fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
 62                 video_writer = cv2.VideoWriter(output_fullname, fourcc, video_fps, frame_size)
 63 
 64                 print(f"Info: writing \'{output_fullname}\' - {file_index}/{filecount}\n... ")
 65 
 66                 while True:
 67 
 68                     # Read a frame
 69                     is_success, bgr_im = video_cap.read() 
 70 
 71                     # Break when no more frame
 72                     if not is_success:
 73                         video_writer.release()
 74                         video_cap.release()
 75                         break
 76 
 77                     # Write current frame to output file
 78                     if ((frame_index % dura_frames) != 0):
 79                         if video_writer.isOpened():
 80                             video_writer.write(bgr_im)
 81 
 82                     # Final frame of the current output file:
 83                     # 1. write the final frame , 2. close output file, 3. create next output file
 84                     if ((frame_index % dura_frames) == 0):
 85                         if video_writer.isOpened():
 86                             video_writer.write(bgr_im)
 87                             video_writer.release()
 88 
 89                             file_index += 1
 90                             output_fullname = "{0}/{1}_{2:03d}{3}".format(sdir, fileObj[0], file_index, fileObj[1])
 91                             video_writer = cv2.VideoWriter(output_fullname, fourcc, video_fps, frame_size)
 92 
 93                             print(f"Info: writing \'{output_fullname}\' - {file_index}/{filecount}\n... ")
 94 
 95                     frame_index += 1
 96 
 97                 video_cap.release()
 98 
 99 
100             # 命令行入口
101             if __name__=="__main__":
102                 msg = """Usage: python %s [file] [seconds] [sdir]
103                 file - Source file, full path
104                 seconds - Duration, default 10 seconds
105                 sdir - Output dir
106                 """
107                 count = len(sys.argv)
108                 if count < 2:
109                     print(msg % sys.argv[0])
110                 elif count == 2:
111                     dura = default_seconds
112                     sdir = osp.abspath('.') + save_dir
113                     splitFile(sys.argv[1], dura, sdir)
114                 elif count == 3:
115                     dura = int(sys.argv[2])
116                     if dura < default_seconds:
117                         dura = default_seconds
118                     sdir = osp.abspath('.') + save_dir
119                     splitFile(sys.argv[1], dura, sdir)
120                 else:
121                     dura = int(sys.argv[2])
122                     if dura < default_seconds:
123                         dura = default_seconds
124                     sdir = sys.argv[3]
125                     if sdir.isspace() == True: 
126                         sdir = osp.abspath('.') + save_dir
127                     splitFile(sys.argv[1], dura, sdir)


    3) 运行

        $ docker exec -t python_media-3.8 python /home/docker/python_media/work/scripts/opencv_split.py /home/docker/python_media/work/res/test.mp4 5

            Info: opening '/home/docker/python_media/work/res/test.mp4' ...
            Info: split to 3 files ...
            Info: writing '/home/docker/python_media/work/out/test_001.mp4' - 1/3
            ...
            Info: writing '/home/docker/python_media/work/out/test_002.mp4' - 2/3
            ...
            Info: writing '/home/docker/python_media/work/out/test_003.mp4' - 3/3
            ...

 

        分割后的小视频在 /home/docker/python_media/work/out 目录,可以正常播放,但没有音频(声音),test_001.mp4 ~ test_002.mp4 时长都是 5 秒,test_003.mp4 时长 4 秒。

        注:以上程序分割的小视频,没有音频(声音),而且生成的文件比源文件还大,这是因为输出文件时没有设置比特率。本文只演示如何分割文件,Opencv 的音频和参数的设置在以后关于 Opencv 的文章里再讲解。简单的文件分割,建议使用 Moviepy 来实现。

 

8. Moviepy 程序

    1) 创建脚本

        $ cd /home/docker/python_media/work/scripts
        $ vim moviepy_split.py

 1             #!/usr/bin/python3
 2 
 3             import os, sys
 4             import os.path as osp
 5 
 6             from moviepy import editor
 7 
 8             # 默认值
 9             save_dir = '/out2'
10             default_seconds = 1
11             max_count = 999
12 
13             # 分割函数
14             def splitFile(filename, dura, sdir):
15                 if filename.isspace() == True or dura < default_seconds or sdir.isspace == True:
16                     print("Error: invalid parameters")
17                     return
18 
19                 if osp.exists(filename) != True:
20                     print(f"Error: \'{filename}\' not exists")
21                     return
22 
23                 if osp.exists(sdir) != True:
24                     os.mkdir(sdir)
25 
26                 print(f"Info: opening \'{filename}\' ...")
27                 video_clip = editor.VideoFileClip(filename)
28                 duration_end = video_clip.duration
29                 if duration_end <= dura:
30                     print(f"Error: video duration {video_clip.duration} seconds <= {dura} seconds, unable to split")
31                     return 
32 
33                 filecount = int(duration_end // dura)
34                 if (duration_end % dura) > 1.0:
35                     filecount += 1
36 
37                 if filecount > max_count:
38                     print(f"Error: file count {filecount} > {max_count}, unable to split")        
39                     return
40 
41                 print(f"Info: split to {filecount} files ...")
42                 # 
43                 fileObj = osp.splitext(osp.basename(filename))
44 
45                 i = 1
46                 start = 0
47                 end = dura 
48                 while i <= filecount:
49 
50                     if start > duration_end:
51                         break
52 
53                     if end > duration_end:
54                         end = duration_end 
55 
56                     sub_clip = video_clip.subclip(start, end)
57                     sub_clip.write_videofile("{0}/{1}_{2:03d}{3}".format(sdir, fileObj[0], i, fileObj[1]))
58 
59                     print(f"Info: in progress -> {i} / {filecount}\n")
60 
61                     start += dura
62                     end += dura
63                     i += 1 
64 
65 
66             # 命令行入口
67             if __name__=="__main__":
68                 msg = """Usage: python %s [file] [seconds] [sdir]
69                 file - Source file, full path
70                 seconds - Duration, default 10 seconds
71                 sdir - Output dir
72                 """
73                 count = len(sys.argv)
74                 if count < 2:
75                     print(msg % sys.argv[0])
76                 elif count == 2:
77                     dura = default_seconds
78                     sdir = osp.abspath('.') + save_dir
79                     splitFile(sys.argv[1], dura, sdir)
80                 elif count == 3:
81                     dura = int(sys.argv[2])
82                     if dura < default_seconds:
83                         dura = default_seconds
84                     sdir = osp.abspath('.') + save_dir
85                     splitFile(sys.argv[1], dura, sdir)
86                 else:
87                     dura = int(sys.argv[2])
88                     if dura < default_seconds:
89                         dura = default_seconds
90                     sdir = sys.argv[3]
91                     if sdir.isspace() == True: 
92                         sdir = osp.abspath('.') + save_dir
93                     splitFile(sys.argv[1], dura, sdir)

 

    2) 运行

        $ docker exec -t python_media-3.8 python /home/docker/python_media/work/scripts/moviepy_split.py /home/docker/python_media/work/res/test.mp4 5   

            Info: opening '/home/docker/python_media/work/res/test.mp4' ...
            Info: split to 3 files ...
            Moviepy - Building video /home/docker/python_media/work/out2/test_001.mp4.
            MoviePy - Writing audio in test_001TEMP_MPY_wvf_snd.mp3
            MoviePy - Done.
            Moviepy - Writing video /home/docker/python_media/work/out2/test_001.mp4

            Moviepy - Done !
            Moviepy - video ready /home/docker/python_media/work/out2/test_001.mp4
            Info: in progress -> 1 / 3

            Moviepy - Building video /home/docker/python_media/work/out2/test_002.mp4.
            MoviePy - Writing audio in test_002TEMP_MPY_wvf_snd.mp3
            MoviePy - Done.
            Moviepy - Writing video /home/docker/python_media/work/out2/test_002.mp4

            Moviepy - Done !
            Moviepy - video ready /home/docker/python_media/work/out2/test_002.mp4
            Info: in progress -> 2 / 3

            Moviepy - Building video /home/docker/python_media/work/out2/test_003.mp4.
            MoviePy - Writing audio in test_003TEMP_MPY_wvf_snd.mp3
            MoviePy - Done.
            Moviepy - Writing video /home/docker/python_media/work/out2/test_003.mp4

            Moviepy - Done !
            Moviepy - video ready /home/docker/python_media/work/out2/test_003.mp4
            Info: in progress -> 3 / 3

        分割后的小视频在 /home/docker/python_media/work/out2 目录,可以正常播放,音频(声音)正常,test_001.mp4 ~ test_002.mp4 时长都是 5 秒,test_003.mp4 时长 4 秒。

posted @ 2022-10-18 11:40  垄山小站  阅读(936)  评论(0)    收藏  举报