java录屏直播推流

JAVACV实现直播推流

最小依赖

 <properties>
        <javacv.version>1.5.5</javacv.version>
        <system.windowsx64>windows-x86_64</system.windowsx64>
    </properties>


 <!-- javacv+javacpp核心库-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp-platform</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <!-- ffmpeg最小依赖包,必须包含上面的javacv+javacpp核心库 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.3.2-${javacv.version}</version>
            <classifier>${system.windowsx64}</classifier>
        </dependency>
        <!-- javacv+javacpp核心库-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp-platform</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <!-- ffmpeg最小依赖包,必须包含上面的javacv+javacpp核心库 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.3.2-${javacv.version}</version>
            <classifier>${system.windowsx64}</classifier>
        </dependency>
        <!-- javacv+javacpp核心库-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp-platform</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <!-- 最小opencv依赖包 ,必须包含上面的javacv+javacpp -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv</artifactId>
            <version>4.5.1-${javacv.version}</version>
            <classifier>${system.windowsx64}</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>openblas</artifactId>
            <version>0.3.13-${javacv.version}</version>
            <classifier>${system.windowsx64}</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>flycapture</artifactId>
            <version>2.13.3.31-${javacv.version}</version>
            <classifier>${system.windowsx64}</classifier>
        </dependency>

视频采集源可以使用摄像头或者其他,我这里用了桌面录像
也排除了声音的采集

package com.test.utiles;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;

/**
 * @author yudy
 * Created by 2022/9/10
 */
@Slf4j
public class MyLiveTest {

    private static int frameRate = 16;// 录制的帧率
    static Frame imgFrame = null;
    static String url = "";
    static boolean isStop = false;

    public static void start() throws Exception {
        // 帧记录
        // window 建议使用 FFmpegFrameGrabber("desktop") 进行屏幕捕捉
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("desktop");
        grabber.setFormat("gdigrab");
        grabber.setFrameRate(frameRate);// 帧获取间隔

        grabber.setOption("framerate", "25");
        grabber.setOption("draw_mouse", "0");
        // 捕获指定区域,不设置则为全屏
//        grabber.setImageHeight(600);
//        grabber.setImageWidth(800);
        // grabber.setOption("offset_x", "200");
        // grabber.setOption("offset_y", "200");//必须设置了大小才能指定区域起点,参数可参考 FFmpeg 入参
        grabber.start();
        //初始化默认帧,用于锁屏状态下无法或者图形的问题导致异常
//        if (imgFrame == null){
//            InputStream in = this.getClass().getClassLoader().getResourceAsStream("img.jpeg");
//            BufferedImage image = ImageIO.read(in);
//            Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
//            imgFrame = java2dConverter.convert(image);
//        }

        if (StringUtils.isEmpty(url)) {
            url = "rtmp://192.168.0.25:1935/live/livestream/aa";
        }
        // 直播推流
        //推送固定大小分辨率的图像
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
                url,
                1024, 768, 0);
        //推送实际小打分辨率的图像
//        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
//                url,
//                grabber.getImageWidth(), grabber.getImageHeight(), 0);
        recorder.setMaxDelay(5000);

        // 用于存储视频 , 调用stop后,需要释放,就会在指定位置输出文件,,这里我保存到D盘
        //FFmpegFrameRecorder recorder = FFmpegFrameRecorder.createDefault(file, grabber.getImageWidth(), grabber.getImageHeight());
        recorder.setInterleaved(true);
        // https://trac.ffmpeg.org/wiki/StreamingGuide
        recorder.setVideoOption("tune", "zerolatency");// 加速  零延迟
        //recorder.setVideoOption("flvflags", "no_duration_filesize");// 加速
        // https://trac.ffmpeg.org/wiki/Encode/H.264
        recorder.setVideoOption("preset", "ultrafast");
        recorder.setFrameRate(frameRate);// 设置帧率,重要!
        // Key frame interval, in our case every 2 seconds -> 30 (fps) * 2 = 60
        recorder.setGopSize(frameRate * 2);
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);// 编码,使用编码能让视频占用内存更小,根据实际自行选择
//        recorder.profile(AVCodecContext.FF_PROFILE_H264_CONSTRAINED_BASELINE);
        // https://trac.ffmpeg.org/wiki/Encode/H.264
        recorder.setVideoOption("crf", "28");
        // 2000 kb/s  720P
        recorder.setVideoBitrate(1000000);
        recorder.setFormat("flv");


        recorder.start();
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    // 获取屏幕捕捉的一帧
                    // 屏幕录制,由于已经对音频进行了记录,需要对记录时间进行调整即可
                    // 即上面调用了 recorder.recordSamples 需要重新分配时间,否则视频输出时长等于实际 的2倍
//                    while ((frame = grabber.grab()) != null) {
                    boolean isGdi = false;
                    int screenW = grabber.getImageWidth();
                    int screenH = grabber.getImageHeight();
                    while (true) {
                        if (isStop) {
                            try {
                                // 停止
                                recorder.stop();
                                grabber.stop();
                                // 释放内存,我们都知道c/c++需要手动释放资源
                                recorder.release();
                                grabber.release();
                                log.info("停止直播完成");
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            break;
                        }
                        Frame frame = grabber.grabFrame();
                        if (frame == null) {
                            isGdi = true;
                            frame = imgFrame;
                        } else if (isGdi) {
                            //先判断分辨率
                            int screenWt = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
                            int screenHt = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
                            if (screenWt == screenW && screenHt == screenH) {
                                log.info("分辨率没有变化,无需重置");
                                isGdi = false;
                            } else {
                                log.info("分辨率有变化,需要重置,马上停止");
                                isStop = true;
                            }
                        }
                        recorder.record(frame);
                    }
                } catch (Exception e) {
                    isStop = true;
                    e.printStackTrace();
                }
            }

        }).start();
    }

    public static void main(String[] args) throws Exception {
        start();
    }

}

可以用docker起一个srs进行推流播放。

# 先启动
docker run -p 1935:1935 -p 1985:1985 -p 8080:8080 \
    ccr.ccs.tencentyun.com/ossrs/srs:4

在这里插入图片描述

再启动推流

效果图:

本示例使用的是SRS,也可以更新为其他的平台服务!启动后SRS控制台上就可以看见当前的直播流了

在这里插入图片描述
也可以进行预览,预览效果图图下:

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以使用以下命令进行FFmpeg直播推流: ``` ffmpeg -i rtsp://121.xxxxxxxxxxxxx:554/xxxxxxxxxxxd8-0-0 -c copy -f hls -hls_list_size 0 -hls_time 5 -hls_list_size 50 -hls_flags 50 你本地根目录地址\test\hls\test.m3u8 ``` 这个命令将从指定的rtsp地址获取视频流,并将其转换为HLS格式,并保存到本地目录中的test.m3u8文件中。\[1\] 如果您遇到找不到文件的问题,可能是由于以下原因: 1. 您提供的rtsp地址不正确或无法访问。请确保地址正确,并且您的网络连接正常。 2. 您指定的本地目录地址不正确。请确保您输入的路径是正确的,并且您具有写入权限。 另外,您还可以参考以下链接获取更多关于FFmpeg直播推流的信息: - https://blog.csdn.net/weixin_45807901/article/details/129086344 - https://blog.csdn.net/T__zxt/article/details/126827167 \[2\] 如果您想使用Docker来进行推流播放,您可以使用以下命令启动一个SRS容器: ``` docker run -p 1935:1935 -p 1985:1985 -p 8080:8080 ccr.ccs.tencentyun.com/ossrs/srs:4 ``` 这将在您的本地启动一个SRS容器,用于推流和播放。\[3\] #### 引用[.reference_title] - *1* [ffmpeg做视频推流直播](https://blog.csdn.net/weixin_38710804/article/details/130846934)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [FFmpeg/opencv + C++ 实现直播拉流和直播推流(对视频帧进行处理)](https://blog.csdn.net/weixin_43482623/article/details/130921255)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [java录屏直播推流](https://blog.csdn.net/qq_36907296/article/details/128816305)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值