文档章节

ffmpeg 踩坑实录 近期使用总结(三)

o
 osc_a22drz29
发布于 2019/03/28 10:33
字数 1133
阅读 15
收藏 0

精选30+云产品,助力企业轻松上云!>>>

一、背景介绍

    将ffmpeg运用到项目上已经有一段时间了,趁现在有空赶紧记下来。

二、技术点总结

   2.1 实现方式

    项目里面主要运用的形式是,在java端,调用操作系统的方法,并执行切片命令。

在执行切片之前,出于对代码的健壮性考虑,一般会下意识地对文件和目标地址进行检查和创建路径。

这里除了,判断传入的String对象是否为空之外,还需要对实际的文件进行判断以及目标地址的路径是否存在。这样可以在发布上线之后避免很多问题。

  2.2 时长的获得

    除了切片还需要,统计被切片的文件时长,这个是后来的需求。针对这个问题,有两种解决方案,一种是调用以下两个依赖包

import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;

 即使用jave的包去解决,但实际原理也是使用ffmpeg的方式去截取时间长短。我使用过这个方案,除了遇到了maven库下载不到,并且需要自己去官网下载,并上传到本地库这一系列操作之后,我仍然遇到了时不时的空指针异常。

这个错误,让我很抓狂,尤其这个jave这个东西我并不熟悉的情况下。第二种方案,偶然的情况下 我执行ffmpeg命令的时候发现

         

其实是有duration 这个数值的。那么我当时就想,是不是我执行命令并把返回的内容进行截取,再转换我就可以得到视频的时长。于是这就是第二个方案,并且已经在使用了。这个方法更加稳定,并且依赖性更少。、

 2.3 切片请求的实现

  其实切片这个操作,主要是对cpu 有高的要求,同时系统又要求实时。所以我采取的办法,是通过nginx 来分发切片的请求,并且把切片服务独立出来,并用线程池的方式来实现。

这样,需要切片的主业务程序,只需要将切片的相关参数发给切片服务,切片服务接受到参数之后立即返回接受成功,等到切片完成之后,再回调主业务的结果接收接口即可。说起来负责,画图就很简单,见下图:

                            

   在发送切片请求的时候,实际上是被nginx拦截的,然后平均转发到几台后台切片服务,这样子就可以避免大量的切片任务会导致单点切片直接卡死(具体表现就是切片切到一定程度,就停止了,我还没找到具体原因,但是我怀疑跟linux 最大文件数限制有有关系)。

这里要注意监控服务器的cpu相关属性 (top 、sar -u)等

2.4 结果的记录

  在之前的方案中,实际上只采取的各个切片服务直连数据库的方式。当完成切片任务之后,就直接连数据库去修改。后来,我想了一下,这个方案是有问题的,尤其是在多点部署的情况下。如果同样的切片请求,被请求两次,并且被转发到不同的节点,这样子不仅切片相互会干扰,同时,在去数据库记录update的时候,有可能会导致死锁。后来将这个方式改为回调接口,把连接数据库的session归拢到主业务中去。

2.5 待完善

事实上,这个业务模块还有很多需要完善的,比如系统的资源监控防止异常的任务波动,日志报警,消息队列来接受切片请求,并且防止重复执行切片任务以及最重要的 切片优化(语句的优化以及 后期考虑上GPU的想法)等。还有,在返回的时候标记这个任务是哪台机器执行的。这样更好的方便,事后,去追溯问题的原因。

三、总结

  做完这个项目之后,越发地感觉把任务拆分成为一个一个简单的单元的重要性(WBS)。构建高内聚,低耦合的系统,也不再是一句口号。是需要认真去思考的,并且一个无法回避的问题。

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

Springboot+Redis综合运用/缓存使用

项目引入依赖(安装redis自行百度) <!-- spring-boot redis --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactI......

心田已荒
9分钟前
0
0
puppeteer csdn 登录 [失败, 跨域cookie无法解决]

使用 puppeteer 登录csdn 暂时没能解决这个问题 滑块可以滑到右边 原因在于cookie const puppeteer = require('puppeteer');const uid = '===';const pwd = '===';(async () => { ......

阿豪boy
28分钟前
9
0
即使使用__init__.py,也如何解决“尝试以非软件包方式进行相对导入”

问题: I'm trying to follow PEP 328 , with the following directory structure: 我正在尝试使用以下目录结构来遵循PEP 328 : pkg/ __init__.py components/ core.py __init_......

富含淀粉
28分钟前
19
0
Java线程池

前言 Java中对线程池的抽象是ThreadPoolExecutor类,Executors是一个工具类,内置了多种创建线程池的方法: newFixedThreadPool:固定长度线程池 newCachedThreadPool :可缓存线程池 newSin...

nullpointerxyz
35分钟前
43
0
Python笔记:用Python制作二维码

这些年,二维码在我国的日常使用频率特别大。因为其具有简单及安全性吧!除了用网络工具制作二维码,其实用JavaScript或Python也可以制作二维码,而且更有个性。 示例一(制作普通黑白二维码...

tengyulong
47分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部