前言

因最近项目需求涉及计算机视觉相关内容,需要实现在Python录制视频,并且录制完成后可在浏览器前端中进行视频回放的功能;特写下此篇文章以记录整体实现过程。

2019-08-02 更新

之前一直在忙别的事,没有继续深入探究,这篇文章也暂时搁置了;但是最近发现之前的实现方式(录制avi视频后由Java调用FFmpeg转换为mp4)会影响到系统的性能,原因为调用FFmpeg转换视频时CPU占用较高QAQ,于是在此前的基础上继续寻找解决方式。

降低FFmpeg的CPU占用

既然FFmpeg的CPU占用较高,那么我们首先尝试如何降低对CPU的占用,搜索发现可以在FFmpeg命令中添加-threads参数来指定CPU的使用

FFmpeg转换测试

此次测试均使用相同avi视频文件,大小为113

1. 原始转换命令

ffmpeg -i test.avi -vcodec libx264 -f mp4 test.mp4

# 转换用时 30s~31s

# CPU占用 950%~1000%

复制代码

2. 添加-threads 6参数

ffmpeg -i test.avi -threads 6 -vcodec libx264 -f mp4 test.mp4

# 转换用时 45s~46s

# CPU 占用490%~550%

复制代码

3. 添加-threads 2参数

ffmpeg -i test.avi -threads 2 -vcodec libx264 -f mp4 test.mp4

# 转换用时 87s~88s

# CPU占用 205%~230%

复制代码

可以看出,添加-threads参数后CPU的占用确实少了,但相应的视频转换耗时也增加了,显然这不是我们想要的效果;所以还是逃避不了录制H264视频的问题

编译安装OpenCV录制视频

之前一直无法录制H264编码的MP4视频是因为使用的为pip安装的opencv-python,这个库中自带FFmpeg,所以不论我们如何折腾系统的FFmpeg都不会有任何作用;如果我们想要调用系统的FFmpeg则需要手动编译安装OpenCV。具体原因可以参考下图:

如何编译安装OpenCV就不过多叙述了,这也不是此篇文章的重点,但还是给懒癌患者放个链接吧! Ubuntu16.04 install OpenCV with ffmpeg

编译安装后import cv2正常引入即可,代码就不放了,原文和网上都有,只是改个fourcc。

至此在Python中调用OpenCV录制H264编码的MP4视频已经可以实现,没有特殊需求的同学看到这里就可以了~撒花!

使用vidgear库录制视频

因为项目原因我们还不能使用手动编译的OpenCV(WTF!!!),所以不得不继续寻找解决方案QAQ

vidgear-github官方链接,这个方案已经脱离主题,只是由于项目原因而采用,在此就不过多叙述了,感兴趣的同学可以看一下。

以下内容为原文

Python-OpenCV录制视频

环境

python 3.7.1

opencv-python 3.4.4.19

引入库支持

import cv2

复制代码

调用摄像头

入参传入“0”、“1”、“2”等数字为摄像头索引,0为自带摄像头,可按顺序调用摄像头,也可传入视频文件路径

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)

指定视频编解码

需要传入fourcc(four character code)四字符编解码代码: fourcc参考

encode = cv2.VideoWriter_fourcc(*'mp4v')

复制代码

初始化VideoWriter

入参参考:官方文档

out = cv2.VideoWriter( './test.mp4', encode, 10, (width, height), True)

复制代码

获取图像帧并写入视频文件

循环从摄像头/视频中获取单帧图像

新开一个窗口展示图像帧,每隔25毫秒播放下一帧,键入“q”跳出循环

将图像帧写入视频文件

while True:

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()

复制代码

完整代码

此处代码为演示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()

复制代码

浏览器中播放视频

环境

macOS Mojave 10.14.3

Ubuntu 16.04

vue 2.9.6

nginx 1.15.5

前端为vue项目,打包后部署在nginx,配置server块/location块提供图片/视频等静态资源访问

h5中video无法播放视频问题

问题排查

代码错误

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中播放,见下图:

尝试更改fourcc重新录制视频

encode = cv2.VideoWriter_fourcc(*'X264')

复制代码

貌似不支持这个编解码QAQ,好像需要FFmpeg的库,Ubuntu下在终端输入:

$sudo apt-get install ffmpeg x264 libx264-dev

复制代码

安装完成后Ubuntu上无法录制(视频文件都无法生成),但是在我自己的电脑不影响录制:

Java使用FFmpeg转换视频

因暂时未能实现录制H.264编解码的MP4视频,所以采用迂回战术:在python中录制.avi格式视频后,前端请求后台,在java中使用FFmpeg将.avi格式视频转换为.mp4格式视频

首先安装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视频上投入过多精力,可能未来会继续尝试~

如有疑问或遇到类似需求可以留言或私信我~

如能实现录制.264视频或有更优解决方案也请不吝赐教~

参考链接

opencv录制视频 python_Python-OpenCV录制H264编码的MP4视频相关推荐

  1. FFmpeg4入门13:h264编码为mp4

    上一篇将yuv源视频文件编码为*.h264的由libx264实现压缩的文件,将源文件从55M编码为620KB,但是h264文件只有视频数据,而且使用范围不太广.那么就需要进一步的封装,在此选用最常用的 ...

  2. opencv录制视频 python_Python同时录制屏幕、摄像头、声音合成视频把人像放在最终视频右下角...

    原标题:Python同时录制屏幕.摄像头.声音合成视频把人像放在最终视频右下角 封面图片:<Python程序设计实验指导书>(ISBN:9787302525790),董付国,清华大学出版社 ...

  3. Android音视频【一】H264编码基础

    人间观察 岁月催人,时间过的太快了 音视频编码解码就是指通过特定的压缩/解压技术,将某个音视频格式的数据转换为另一种音视频格式数据.目前在Android中的音视频用的最多的就是H264+aac的方式进 ...

  4. 超越苹果索尼 艾诺兼容H264编码全格式视频

    发展到现在,H.264编码视频凭借优秀的画面质量,逐渐成为视频编码领域的无冕之王,众多视频压制小组和视频下载网站都将H264编码的视频作为高清爱好者的必然选择,其资源占有率逐渐向着RMVB.AVI等前 ...

  5. 使用FFmpeg将视频编码格式转化为H264编码

    背景介绍: web开发中涉及到视频播放的前端一般会使用h5的video标签对后端提供的视频文件url直接加载进行播放,虽然视频文件后缀都是mp4,但并非所有视频文件的编码格式都支持用video播放,目 ...

  6. SONY索尼微单a6300/a7相机提示需要修复视频打不开,如何修复MP4视频?

    索尼微单a6300/a7在视频录制中,异常原因导致相机显示文件错误,需要修复,点了修复之后却发现视频还是无法播放,使用播放器打开提示: 但是文件是显示有大小的,3.43G,说明视频是有数据的,但是相机 ...

  7. python视频转化_python实现m3u8格式转换为mp4视频格式

    开发动机:最近用手机QQ浏览器下载了一些视频,视频越来越多,占用了手机内存,于是想把下载的视频传到电脑上保存,可后来发现这些视频都是m3u8格式的,且这个格式的视频都切成了碎片,存在电脑里不方便查看, ...

  8. 压缩视频最好最快的软件?mp4视频太大怎么压缩格式工厂?

    经常有朋友问我手机录的视频太大了怎么压缩,我也找了很多软件,但是都不怎么样好用,小编今天给小伙伴们介绍一个简单的方法视频压缩软件,我在这里介绍一个简单的方法来压缩视频体积: 1:你设置输出格式时是不是 ...

  9. android gpu 视频编码,Android Mp4视频录制(OpenGL实现篇,附DEMO)

    上一篇中(http://www.jianshu.com/p/113e4eedb752),我们已经了解了视频录制的大概流程,以及部分关键代码,在这一篇,我给大家介绍借助OpenGL来对视频图像进行处理的 ...

最新文章

  1. 设备节点注册和操作方法连接
  2. .Lucky后缀勒索病毒数据解密
  3. ubtunu查看服务器信息,ubuntu查看服务器地址
  4. 笔记(用Python做些事情)--变量(数字、字符串)
  5. 博弈论——关于Nim游戏和SG函数的几个链接
  6. nonlocal和global关键字
  7. 送书丨《架构解密:从分布式到微服务》
  8. 如何在Javascript中创建范围
  9. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数 列表表达式/列表重写...
  10. SqlServer 存贮过程操作类
  11. 忘记压缩包密码 python 暴力破解rar密码
  12. [Error] invalid operands of types ‘int‘ and ‘double‘ to binary ‘operator‘
  13. 100种网站推广方法全集
  14. 一个自动生成卡通头像的工具网站
  15. 程序人生之项目团队那些人与事(1)
  16. 如何以编程方式执行Unwind segue?
  17. RDKit | 计算拓扑极性表面积TPSA
  18. 转载:ZedGraph使用帮助
  19. java基于web的工资管理系统
  20. [Sentinel 笔记] Sentinel的流量控制和降级

热门文章

  1. 常见的Http状态码以及其代表的意义
  2. 【题解】NOIP-2016 天天爱跑步
  3. 001-REST-简介
  4. 解决XAMPP中无法勾选/无服务/modules无反应/Service灰框/无✓X/提供虚拟服务器
  5. CSS真好玩——用纯CSS画一轮新月
  6. 2020-9-20 周报
  7. 量化交易有因子动物园 深度学习里有模型动物园(ModelZoo)又叫模型市场基于深度学习的增量学习,迁移学习等技术发展而来【调研】
  8. AutoCAD关于选择的一些技巧(如何高效地框选)
  9. 如何做Unity手游性能优化的
  10. 数据库学习笔记—MySQL技术nei幕—第一章—MySQL体系结构和存储引擎