" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaCV 拉流存儲(chǔ)到本地示例解析

 更新時(shí)間:2023年08月03日 09:03:06   作者:JinYx  
這篇文章主要介紹了JavaCV 拉流存儲(chǔ)到本地示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

拉流整體代碼

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
public class LivePuller {
    public void pull(String rtmp, String outputVideoPath) {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        try {
            FFmpegLogCallback.set();
            boolean hasStream = false;
            grabber = new FFmpegFrameGrabber(rtmp);
            grabber.setOption("nobuffer", "1");
            // 采集流超時(shí)時(shí)間,停止推流后,grab() 大致會(huì)在 20 秒左右超時(shí)停止;值也不宜太小,否則可能有些音視頻幀采集不到影響推流
            grabber.setOption("rw_timeout", "1000000");
            grabber.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
            // setPixelFormat,可能會(huì)導(dǎo)致圖片幀保存的是黑白照
//            grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            grabber.setFormat("flv");
            grabber.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
            // 先執(zhí)行代碼后有直播流的情況下,grabber.start() 會(huì)拋出異常;因此循環(huán)start(),直到有流數(shù)據(jù)時(shí)成功
            while (!hasStream) {
                try {
                    grabber.start();
                    hasStream = true;
                } catch (Exception ignored) {
                } finally {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            // 重置分辨率
            int imageWidth = grabber.getImageWidth();
            int imageHeight = grabber.getImageHeight();
            if (imageWidth > 1920 || imageHeight > 1080) {
                double wScale = imageWidth * 1.0 / 1920;
                double hScale = imageHeight * 1.0 / 1080;
                double scale = Math.max(wScale, hScale);
                grabber.setImageWidth((int) (imageWidth / scale));
                grabber.setImageHeight((int) (imageHeight / scale));
            }
            recorder = new FFmpegFrameRecorder(outputVideoPath, grabber.getImageWidth(), grabber.getImageHeight());
            recorder.setOption("nobuffer", "1");
            recorder.setAudioChannels(grabber.getAudioChannels());
            recorder.setFrameRate(grabber.getFrameRate());  // 保持和采集一樣的幀率,避免音畫不同步;
            recorder.setVideoQuality(0);    // 視頻質(zhì)量(清晰度)
            recorder.setAudioQuality(0);    // 音頻質(zhì)量
            // --------------------------- 非必須 ------------------------------
            // 當(dāng)設(shè)置了下方的錄制器的視頻編碼,需要再加上 setVideoBitrate 保證視頻質(zhì)量
            recorder.setVideoBitrate(grabber.getVideoBitrate());
            recorder.setVideoCodec(grabber.getVideoCodec());    // 指定為 mp4 錄制時(shí)需要 avcodec.AV_CODEC_ID_MPEG4
//            // 當(dāng)上面 grabber 沒(méi)有設(shè)置 setPixelFormat,recorder.setPixelFormat 最好不要使用 grabber.getPixelFormat();可能異常
//            recorder.setPixelFormat(grabber.getPixelFormat());
//            recorder.setFormat(grabber.getFormat());
//            recorder.setAudioCodec(grabber.getAudioCodec());
//            recorder.setSampleRate(grabber.getSampleRate());
            recorder.start();
            Frame frame;
            while ((frame = grabber.grab()) != null) {
                // 此處不能判斷 frame.streamIndex 為 avutil.AVMEDIA_TYPE_VIDEO 或 avutil.AVMEDIA_TYPE_DATA;遇到過(guò)采集流時(shí)兩個(gè)類型是反著的
                if (frame.image != null || frame.samples != null) {
                    // frame.image 是圖像數(shù)據(jù),frame.samples 是聲音數(shù)據(jù)
                    recorder.record(frame);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (grabber != null) {
                try {
                    grabber.close();
                } catch (FrameGrabber.Exception e) {
                    e.printStackTrace();
                }
            }
            if (recorder != null) {
                try {
                    recorder.close();
                } catch (FrameRecorder.Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

拉流整體代碼如上,基本該有的地方都有注釋;同 JavaCV 推流 也是改變分辨率等參數(shù)保證拉流速率,以及設(shè)置幀率保證音畫同步;

示例解析

另外上面提到 grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); 不要設(shè)置,避免后續(xù)的 JavaCV 保存視頻幀圖片 時(shí)保存的圖片是黑白的;另外上面的代碼經(jīng)過(guò)測(cè)試是可以將拉取的音視頻流保存成 mp4 格式,通過(guò)瀏覽器直接播放的

注意測(cè)試 mp4 文件保存的時(shí)候,盡量每次寫入一個(gè)新的文件;避免在調(diào)試過(guò)程中,出現(xiàn)因?yàn)g覽器緩存等問(wèn)題導(dǎo)致之前有問(wèn)題的 mp4 的文件,在參數(shù)調(diào)整好后依然不能正常播放等情況

以上就是JavaCV 拉流存儲(chǔ)到本地示例解析的詳細(xì)內(nèi)容,更多關(guān)于JavaCV 拉流存儲(chǔ)到本地的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringAop的依賴注入方式

    SpringAop的依賴注入方式

    文章介紹了Spring框架的依賴注入(DI)和面向切面編程(AOP)的基本概念和實(shí)現(xiàn)方式,Spring通過(guò)IOC容器管理Bean的創(chuàng)建和依賴注入,并提供了多種AOP實(shí)現(xiàn)方式,包括代理機(jī)制和配置選項(xiàng)
    2025-02-02
  • springboot2.0整合dubbo的示例代碼

    springboot2.0整合dubbo的示例代碼

    這篇文章主要介紹了springboot2.0整合dubbo的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 1小時(shí)快速上手RabbitMQ(簡(jiǎn)介及安裝過(guò)程)

    1小時(shí)快速上手RabbitMQ(簡(jiǎn)介及安裝過(guò)程)

    RabbitMQ簡(jiǎn)稱MQ全稱是Message Queue(消息隊(duì)列),是在消息的傳輸過(guò)程中保存消息的容器,多用于分布式系統(tǒng)之間進(jìn)行通信,本文給大家講解了RabbitMQ簡(jiǎn)介與安裝,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友跟隨小編一起看看吧
    2023-01-01
  • Java線程池實(shí)現(xiàn)帶返回值的方式方法

    Java線程池實(shí)現(xiàn)帶返回值的方式方法

    在Java中,線程池是一種重要的多線程處理方式,可以有效管理和重用線程,提高程序的性能和效率,有時(shí)候我們需要在多線程處理中獲取線程的返回值,本文將介紹如何使用線程池實(shí)現(xiàn)帶返回值的方式方法,需要的朋友可以參考下
    2024-09-09
  • IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程

    IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程

    項(xiàng)目開發(fā)時(shí)使用Intellij IDEA連接本地?cái)?shù)據(jù)庫(kù),將數(shù)據(jù)庫(kù)可視化,還可對(duì)數(shù)據(jù)庫(kù)表直接進(jìn)行增刪改查操作,方便快捷又清晰,下面這篇文章主要給大家介紹了關(guān)于IDEA連接Mysql數(shù)據(jù)庫(kù)的詳細(xì)圖文教程,需要的朋友可以參考下
    2023-03-03
  • Java編程 多態(tài)

    Java編程 多態(tài)

    這篇文章主要介紹了關(guān)于Java編程的多態(tài),多態(tài)通過(guò)分離做什么和怎么做,從另一個(gè)角度將接口和實(shí)現(xiàn)分離開來(lái)。構(gòu)建可擴(kuò)展的程序,需要的朋友可以參考下
    2021-10-10
  • Idea 2023.2.5配置插件、Maven的過(guò)程

    Idea 2023.2.5配置插件、Maven的過(guò)程

    這篇文章主要介紹了Idea 2023.2.5配置插件、Maven的過(guò)程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • Spring?Framework六種常見設(shè)計(jì)模式

    Spring?Framework六種常見設(shè)計(jì)模式

    設(shè)計(jì)模式是軟件開發(fā)的重要組成部分,本文借助spring來(lái)講解這個(gè)框架的設(shè)計(jì)模式,通過(guò)本文我們探討了spring如何利用這些模式來(lái)提供這些豐富的功能,對(duì)本文感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • Java Socket編程實(shí)例(一)- TCP基本使用

    Java Socket編程實(shí)例(一)- TCP基本使用

    這篇文章主要講解Java Socket編程中TCP的基本使用,希望能給大家做一個(gè)參考。
    2016-06-06
  • SpringSecurity+JWT簡(jiǎn)單集成的實(shí)現(xiàn)

    SpringSecurity+JWT簡(jiǎn)單集成的實(shí)現(xiàn)

    本文主要介紹了SpringSecurity+JWT簡(jiǎn)單集成的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04

最新評(píng)論

安国市| 河北区| 余干县| 集贤县| 中方县| 济阳县| 女性| 霸州市| 新津县| 盐亭县| 晋城| 冕宁县| 霍林郭勒市| 苏尼特右旗| 苏尼特右旗| 杭锦后旗| 永康市| 八宿县| 中阳县| 资兴市| 瓮安县| 平潭县| 英吉沙县| 蚌埠市| 西贡区| 通山县| 孟连| 乐安县| 准格尔旗| 苍梧县| 四会市| 饶阳县| 启东市| 铅山县| 罗定市| 乐昌市| 伊春市| 宁晋县| 扎鲁特旗| 泰顺县| 湟中县|