因最近项目需求涉及计算机视觉相关内容,须要实如今Python录制视频,而且录制完成后可在浏览器前端中进行视频回放的功能;特写下此篇文章以记录总体实现过程。php
以前一直在忙别的事,没有继续深刻探究,这篇文章也暂时搁置了;可是最近发现以前的实现方式(录制avi视频后由Java调用FFmpeg转换为mp4)会影响到系统的性能,缘由为调用FFmpeg转换视频时CPU占用较高QAQ,因而在此前的基础上继续寻找解决方式。html
既然FFmpeg的CPU占用较高,那么咱们首先尝试如何下降对CPU的占用,搜索发现能够在FFmpeg命令中添加-threads
参数来指定CPU的使用前端
这次测试均使用相同avi视频文件,大小为113vue
ffmpeg -i test.avi -vcodec libx264 -f mp4 test.mp4
# 转换用时 30s~31s
# CPU占用 950%~1000%
复制代码
-threads 6
参数ffmpeg -i test.avi -threads 6 -vcodec libx264 -f mp4 test.mp4
# 转换用时 45s~46s
# CPU 占用490%~550%
复制代码
-threads 2
参数ffmpeg -i test.avi -threads 2 -vcodec libx264 -f mp4 test.mp4
# 转换用时 87s~88s
# CPU占用 205%~230%
复制代码
能够看出,添加-threads
参数后CPU的占用确实少了,但相应的视频转换耗时也增长了,显然这不是咱们想要的效果;因此仍是逃避不了录制H264视频的问题java
import cv2
正常引入便可,代码就不放了,原文和网上都有,只是改个fourcc。import cv2
复制代码
入参传入“0”、“1”、“2”等数字为摄像头索引,0为自带摄像头,可按顺序调用摄像头,也可传入视频文件路径python
cap = cv2.VideoCapture(0)
复制代码
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
复制代码
使用摄像头帧率录制视频后播放存在快进状况,暂时写死在VideoWriter中 不知道是否与摄像头有关,此处未进行深刻了解 fps = cap.get(cv2. CV_CAP_PROP_FPS)nginx
须要传入fourcc(four character code)四字符编解码代码: fourcc参考git
encode = cv2.VideoWriter_fourcc(*'mp4v')
复制代码
入参参考:官方文档github
out = cv2.VideoWriter( './test.mp4', encode, 10, (width, height), True)
复制代码
while True:
if cv2.waitKey(25) & 0xFF == ord('q'):
break
ret, frame = cap.read()
cv2.imshow('test', frame)
out.write(frame)
复制代码
out.release()
cap.release()
cv2.destroyAllWindows()
复制代码
此处代码为演示demo,仅供参考跨域
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
# 调用摄像头
cap = cv2.VideoCapture(0)
# 获取摄像头宽高
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 获取摄像头帧率
#fps = cap.get(cv2.CAP_PROP_FPS)
# 指定fourcc编解码
encode = cv2.VideoWriter_fourcc(*'mp4v')
# 初始化VideoWriter
out = cv2.VideoWriter('./test.mp4', encode, 10, (width, height), True)
while True:
# 每隔25毫秒播放下一帧,若键入“q”跳出循环
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# 从摄像头获取下一帧
ret, frame = cap.read()
# 新开窗口展现图像
cv2.imshow('test', frame)
# 将当前帧写入视频文件
out.write(frame)
# 释放VideoWriter
out.release()
# 释放摄像头
cap.release()
# 关闭窗口
cv2.destroyAllWindows()
复制代码
python录制视频是否成功
前端中video的src是否正确
浏览器控制台是否报错
nginx服务是否启动
请求路径是否正确
是否跨域问题
格式 | IE | Firefox | Opera | Chrome | Safari |
---|---|---|---|---|---|
Ogg | - | 3.5+ | 10.5+ | 5.0+ | - |
MPEG 4 | 9.0+ | - | - | 5.0+ | 3.0+ |
WebM | - | 4.0+ | 10.6+ | 6.0+ | - |
格式 | 视频编码 | 音频编码 |
---|---|---|
Ogg | Theora | Vorbis |
MPEG 4 | H.264 | AAC |
WebM | VP8 | Vorbis |
排除代码及网络请求问题后,能够将问题定位在浏览器,我使用的浏览器为Chrome,排除版本问题,所以能够肯定是视频编解码问题,在python中录制视频时未使用H.264编解码:
encode = cv2.VideoWriter_fourcc(*'mp4v')
复制代码
查看视频简介能够发现该视频也确实非H.264编解码,所以形成该视频能够在视频播放软件中正常播放却没法在h5的video中播放,见下图:
encode = cv2.VideoWriter_fourcc(*'X264')
复制代码
$sudo apt-get install ffmpeg x264 libx264-dev
复制代码
安装完成后Ubuntu上没法录制(视频文件都没法生成),可是在我本身的电脑不影响录制:
首先安装FFmpeg (Ubuntu下我没有安装,好像是自带的?) macOS安装FFmpeg Ubuntu安装FFmpeg java这边就再也不详述了,直接上代码~(一样为演示demo,仅供参考)
// FFmpeg转换命令
String transferCommand = "ffmpeg -i filePath/fileName.avi -vcodec libx264 -f mp4 filePath/fileName.mp4";
Process process = Runtime.getRuntime().exec("/bin/bash");
printWriter = new PrintWriter(new BufferedWriter(new
OutputStreamWriter(process.getOutputStream())), true);
printWriter.println(transferCommand);
// 这个命令必须执行,不然in流不结束。
printWriter.println("exit");
printWriter.close();
process.waitFor();
复制代码
转换过程须要些许时间,采起方案为启一条线程完成视频转换,不影响当前接口响应时间,在用户无感知的状况下完成视频转换。
以上内容为本次实现过程记录,代码均为演示demo,非实际应用代码,若有须要可根据实际需求加以调整。由于时间缘由未能在录制H.264视频上投入过多精力,可能将来会继续尝试~