javacv-06:rtsp视频流存储在腾讯云对象存储中---代码比较稚嫩

前言

javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能),这里只使用javacv来实现一些简单的功能,具体到项目中还需要大家自己磨合

重要:

建议使用最新javaCV1.5版本,该版本已解决更早版本中已发现的大部分bug     --博主目前使用的  javaCV1.5.4

javacv系列文章使用6个jar包:

javacv.jar,javacpp.jar,ffmpeg.jar,ffmpeg-系统平台.jar,opencv.jar,opencv-系统平台.jar。

其中ffmpeg-系统平台.jar,opencv-系统平台.jar中的系统平台根据开发环境或者测试部署环境自行更改为对应的jar包,比如windows7 64位系统替换为ffmpeg-x86-x64.jar

为什么要这样做:因为ffmpeg-系统平台.jar中存放的是c/c++本地so/dll库,而ffmpeg.jar就是使用javacpp封装的对应本地库java接口的实现,而javacpp就是基于jni的一个功能性封装包,方便实现jni,javacv.jar就是对9个视觉库进行了二次封装,但是实现的功能有限,所以建议新手先熟悉openCV和ffmpeg这两个C/C++库的API后再来看javaCV思路就会很清晰了。

上一章简单的介绍了 开启本地本地视频直播:javacv-05:开启真正的本地视频直播,添加音频

下面将介绍如何 :

1、依赖配置说明

maven和gradle方式如果想要减小依赖包大小,则需要手动进行排除不需要的平台依赖即可

(注意:从其他地方下载的依赖包请积极开心的替换为官方jar包和博主提供jar包;如果使用其他jar包版本而导致出错,不要急着找博主问为啥会报错,先把jar包替换了再试试看)

(1)使用maven添加依赖

  1. <dependency>

  2. <groupId>org.bytedeco</groupId>

  3. <artifactId>javacv-platform</artifactId>

  4. <version>1.5.4</version>

  5. </dependency>

  6.  

  7. <!-- 腾讯云的COS对象存储--> 

  8.  <dependency>

  9.   <groupId>com.qcloud</groupId>

  10.     <artifactId>cos_api</artifactId>

  11.  <version>5.6.35</version>

  12.  

        </dependency>

(2)使用gradle添加依赖

  1. dependencies {

  2. compile group: 'org.bytedeco', name: 'javacv-platform', version: '1.4.4'

  3. }

(3)使用本地jar包方式

最新版实在太大,需要下载全量包的请到官方github.com/bytedeco/javacv下载

注:博主不太赞同使用这种方式!!!(但还是进行了相关介绍)

jar包使用须知:

1、windows x64平台用到的opencv依赖:opencv.jaroepncv-windows-x86_64.jar(其他平台替换为对应的jar包即可)

2、苹果mac需要opencv-macosx-x86_64.jar
3、linux平台需要:opencv-linux-x86_64.jar  

4、安卓平台arm架构的需要opencv-android-arm.jar ,基于x86的需要opencv-android-x86.jar

2、为什么不需要安装opencv?

从javacv0.8开始,已经不需要本地安装opencv,直接通过引用opencv对应的系统平台的引用包即可。

(比如oepncv-windows-x86_64.jar就是典型的64位windows环境依赖包)

3、代码实现 

本次涉及到两段代码,一个是将rtsp视频流保存在本地并上传至对象存储的代码,另一个是用java实现的定时任务。本次的代码较为稚嫩,望大家轻喷~

第一段为:



import java.io.File;
import java.util.TimerTask;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.StorageClass;
import com.qcloud.cos.region.Region;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

/**
 * 成功实现视频流保存至对象存储中,现阶段需要本地路径进行缓存中转,后续考虑RTMP和对象存储直接对接
 * 腾讯云的cos目前可以免费使用半年,趁着免费薅羊毛
 */
public class SaveRtspCos extends TimerTask {

    private static final String SECRETID = "xxx";  //腾讯云的cos中会给出该值
    private static final String SECRETKEY = "xxx";  //腾讯云的cos中会给出该值
    private static final String BUCKETNAME = "rtsptest"; //桶的名字
    private static final String APPID = "11111"; // 可以在腾讯云官网的右上角点开头像,然后“账户信息”中查看
    private static final String REGIONID = "ap-beijing";// 区域
    private static final String KEY = "Rtsp.avi"; // COS上面存储的名称

    // public static void main(String[] args) {

    // uploadFile();  //本地简单测试时可以放在该方法
    // }

    @Override
    public void run() {
        String inputFile = "rtsp://xxx";   //rtsp视频流地址
        long timestamp = System.currentTimeMillis();  //获取当前时间戳
        String outputFile = "recorde" + timestamp + ".avi";  
        try {
            frameRecord(inputFile, outputFile, 1);
            uploadFile(outputFile);
            System.out.println(outputFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化CosClient相关配置, appid、SECRETID、secretKey、region
     * 
     * @return
     */
    public static COSClient getCosClient() {
        // 1 init userInfo (secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(APPID, SECRETID, SECRETKEY);
        // COSCredentials cred = new BasicCOSCredentials(SECRETID, SECRETKEY); //
        // 不传APPID也可以,APPID和ACCESSKE已经关联过
        // 2 set bucket region
        ClientConfig clientConfig = new ClientConfig(new Region(REGIONID));
        // 3 init cosclient
        COSClient cosclient = new COSClient(cred, clientConfig);
        // bucket name protocol must be {name}-{appid}
        return cosclient;
    }

    /**
     * 上传文件
     * 
     * @return
     */
    public static String uploadFile(String upFile) {
        File localFile = new File(upFile);// 将RTSP视频流保存在本地的内容输入进去
        // PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKETNAME, KEY,
        // localFile);
        PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKETNAME, upFile, localFile);

        // 设置存储类型, 默认是标准(Standard), 低频(standard_ia)
        putObjectRequest.setStorageClass(StorageClass.Standard_IA);

        COSClient cc = getCosClient();
        try {
            PutObjectResult putObjectResult = cc.putObject(putObjectRequest);
            // putobjectResult会返回文件的etag
            String etag = putObjectResult.getETag();
            System.out.println(etag);
        } catch (CosServiceException e) {
            e.printStackTrace();
        } catch (CosClientException e) {
            e.printStackTrace();
        }
        // 关闭客户端
        cc.shutdown();
        return null;
    }

    public static void frameRecord(String inputFile, String outputFile, int audioChannel)
            throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {
        // 设置为全局控制变量,用于控制录制结束
        boolean isStart = true;
        // 获取视频源
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        // 如果不设置成tcp连接时,默认使用UDP,丢包现象比较严重
        grabber.setOption("rtsp_transport", "tcp"); // 设置成tcp以后比较稳定
        // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel);
        // 不进行转码时,编码格式默认为HFYU,使用VLC播放器时无法播放下载的视频 --可能和海康的摄像头有关
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);// avcodec.AV_CODEC_ID_H264,编码

        // 开始取视频源
        recordByFrame(grabber, recorder, isStart);
    }

    private static void recordByFrame(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder, Boolean status)
            throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {
        try {// 建议在线程中使用该方法
            grabber.start();
            recorder.start();
            Frame frame = null;
            long t1 = System.currentTimeMillis();
            while (status && (frame = grabber.grabFrame()) != null) {
                long t2 = System.currentTimeMillis();

                if (t2 - t1 > 50 * 1000) {
                    break;
                }
                recorder.record(frame);
                // cframe.showImage(frame);
            }
            recorder.stop();
            grabber.stop();
        } finally {
            if (grabber != null) {
                grabber.stop();
            }
        }
    }

}

第二段代码为:



import java.util.Timer;

import cos.SaveRtspCos;

public class TimeTest {
    public static void main(String[] args) {
        Timer timer = new Timer();
        // timer.schedule(new Task(), 10 * 1000, 10 * 1000);
        timer.schedule(new SaveRtspCos(), 1 * 1000, 60 * 1000);
        // public void schedule(TimerTask task,long delay,long period)
        // 第一个参数就是我们要执行的任务
        // 第二个参数是一个long型的值,这是延迟的间
        // 第三个参数是间隔的时间
    }
}

本次代码中存在的缺陷是:未能很好的实现定时存储视频流文件,只是简易的实现了每个5分钟存储一段视频。该代码后续将会进行优化。

 

至此,代码已经可以成功运行,在第二段代码中运行即可在腾讯云的cos端看到存储的视频文件,其他人员想看该视频文件时,即可从COS上进行下载。

注:此次代码是基于vscode编辑器进行开发,使用起来很是方便,也是轻量级的;jdk版本为1.8。

大家如有问题可以随时留言~    关注+点赞+转发 走一波~ 
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java,使用FFmpegJavaCV库可以很容易地实现收流器的功能。收流器可以接收来自RTSP或RTMP服务器的视频流,并保为视频文件。以下是一个基于JavaCV-FFmpeg的简单实现。 首先需要添加JavaCVFFmpeg的依赖。可以在Maven使用以下依赖: ``` <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.4</version> </dependency> ``` 接下来是收流器的实现代码: ```java import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Java2DFrameConverter; import org.bytedeco.javacv.JavaFXFrameConverter; import java.awt.image.BufferedImage; import java.io.File; public class StreamReceiver { private FFmpegFrameGrabber grabber; private Java2DFrameConverter frameConverter; private JavaFXFrameConverter fxConverter; private boolean isRunning = false; public void start(String streamUrl, String outputFile) { try { grabber = new FFmpegFrameGrabber(streamUrl); grabber.start(); frameConverter = new Java2DFrameConverter(); fxConverter = new JavaFXFrameConverter(); isRunning = true; while (isRunning) { BufferedImage image = frameConverter.convert(grabber.grab()); if (image != null) { fxConverter.convert(image); } } grabber.stop(); grabber.release(); } catch (Exception e) { e.printStackTrace(); } } public void stop() { isRunning = false; } public static void main(String[] args) { StreamReceiver receiver = new StreamReceiver(); receiver.start("rtmp://live.hkstv.hk.lxdns.com/live/hks", "output.mp4"); } } ``` 在这个实现,`start`方法会创建一个`FFmpegFrameGrabber`对象,并使用给定的`streamUrl`开始抓取。然后使用`Java2DFrameConverter`将抓取的帧转换为`BufferedImage`对象,最后使用`JavaFXFrameConverter`将`BufferedImage`转换为JavaFX的`Image`对象。在循环,我们检查`BufferedImage`是否为空,以确保我们只保有内容的帧。最后,当`stop`方法被调用时,循环止并关闭抓取器。 可以通过调用`StreamReceiver`的`start`方法启动收流器,并使用RTMP或RTSP URL作为参数。收流器将不断抓取视频流,并将其保到指定的输出文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值