java传递参数调用python完成剪切多个视频最终拼接成一个
需求如题,综合考虑之后我选择python去做视频处理,最终结果也让我非常满意。
我是windows 环境,安装的python3.8和moviepy模块
第一步:安装python3.8
第二步:修改python模块下载源,在Roaming下直接新建pip文件夹,新建pip.ini文件
我的路径是C:\Users\用户名\AppData\Roaming\pip\pip.ini 可进行参考,如下:
[global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple [install] use-mirrors = true mirros = https://pypi.mirrors.ustc.edu.cn/simple
第三步:下载moviepy模块
cmd 执行 pip install moviepy
第四步:编写python 剪切拼接视频的代码(123.mp4,456.mp4都是测试视频,自己找一个)
import moviepy import sys from moviepy.editor import * def main(a): print(url) # 打印java 传来的参数 video = VideoFileClip("C:\\Users\\HG\\123.mp4").subclip(1,5)# 表示截取123.mp4的1-5秒 video1 = VideoFileClip("C:\\Users\\HG\\456.mp4").subclip(5,10) video2 = concatenate_videoclips([video,video1])# 拼接两个剪切好的视频 result = CompositeVideoClip([video2]) result.to_videofile("video_1.mp4")# 输出到工作目录下 if __name__ == '__main__': for i in range(0, len(sys.argv)): url = sys.argv[i]# 按数组的方式取出java 传来的参数 main(url)# 执行打印方法
第五步:写java 调用python 脚本的代码,这个地方我了解了一下,有两种办法①引入jython包执行,便捷但不能传参,故舍弃。②用Runtime.getRuntime().exec() 执行,可传参。
保存python执行日志到文件的java
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * @ClassName: StreamReaderThread * @Description: 执行python 脚本打印执行日志 * @Date 2022/10/18 14:28 */ public class StreamReaderThread implements Runnable { private Logger logger = LoggerFactory.getLogger(StreamReaderThread.class); /* * 输出流 */ private InputStream inputStream; /* * 输出信息保存的文件名称 */ private String logName; public StreamReaderThread(InputStream inputStream, String logName) { this.inputStream = inputStream; this.logName = logName; } /** * FileWriter将日志写入某文件 * 也可以用logger打印日志记录。 */ @Override public void run() { BufferedReader in = null; FileWriter fwriter = null; try { in = new BufferedReader(new InputStreamReader(this.inputStream, "gbk")); fwriter = new FileWriter(logName, true); String line = null; while ((line = in.readLine()) != null) { fwriter.write(line); logger.info(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); fwriter.flush(); fwriter.close(); in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
python 调用的java
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.rmi.ServerException; /** * @ClassName: PythonScriptUtils * @Description: 调用python脚本 * @Date 2022/10/18 14:25 */ public class PythonScriptUtils { private static Logger logger = LoggerFactory.getLogger(PythonScriptUtils.class); /** * 执行python脚本 * @param path 文件地址:比如 D:\\xxx\\helloWorld.py */ public static Boolean exePython(String path) throws ServerException { logger.info("======python start"); boolean success = false; Process proc = null; try { // linux 用 "python3", windows 用python.exe的绝对路径("D:\\xxx\\Python\\Python39-32\\python.exe") String a = "hello world"; String url = "www.baidu.com"; // String[] args1 = new String[]{"python3", path,a,url}; //linux 系统使用此代码进行执行 String[] args1 = new String[]{"C:\\Users\\HG\\AppData\\Local\\Programs\\Python\\Python38\\python.exe", path,a,url}; proc = Runtime.getRuntime().exec(args1); // 读写日志线程,分成两个也是为了避免线程堵塞之类的问题,具体原因网络上有很多说明 Thread thread1 = new Thread(new StreamReaderThread(proc.getInputStream(),"info.txt")); Thread thread2 = new Thread(new StreamReaderThread(proc.getErrorStream(),"error.txt")); thread2.start(); //必须后执行,否则正确消息容易接收不到 thread1.start(); // result是结果,具体有哪些值,可以自己去查一下 int result = proc.waitFor(); success = result != -1; //等待后台线程读写完毕 Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); throw new ServerException("python error:" + e); } finally { try { proc.getErrorStream().close(); proc.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); } proc.destroy(); logger.info("======python end"); } return success; } public static void main(String[] args) throws Exception { exePython("C:\\Users\\HG\\test.py"); } }