讀書筆記-第三課

前言

查看了相關文章然後一筆一筆打代碼再調試成功出結果,
eguid的博客
不保證代碼能夠原封不動就能運行,
這裏做一下記錄。
ps:代碼內容有改動,原版的可以看原作者的。

代碼內容

package net.w2p.JCVStudio.zhiboStudy;

import javafx.embed.swing.SwingFXUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.CvScalar;
import org.bytedeco.opencv.opencv_core.IplImage;

import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_imgproc.CvFont;
import org.opencv.core.CvType;
import org.opencv.core.Mat;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.concurrent.ConcurrentHashMap;

import static org.bytedeco.opencv.global.opencv_core.IPL_DEPTH_8U;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

/***
 * 收流器實現,錄製流媒體服務器的rtsp/rtmp視頻文件(基於javaCV-FFMPEG)
 * https://blog.csdn.net/eguid_1/article/details/52680802
 * 順便操作畫面,進行文字打水印。
 * **/
public class Lesson03 {


    private ConcurrentHashMap<String,Object> mapParas=new ConcurrentHashMap<>(55);
    /**
     * 按幀錄製視頻
     *
     * @param inputFile-該地址可以是網絡直播/錄播地址,也可以是遠程/本地文件路徑
     * @param outputFile                              -該地址只能是文件地址,如果使用該方法推送流媒體服務器會報錯,原因是沒有設置編碼格式
     * @throws FrameGrabber.Exception
     * @throws FrameRecorder.Exception
     * @throws org.bytedeco.javacv.FrameRecorder.Exception
     */
    public void frameRecord(String inputFile, String outputFile, int audioChannel)
            throws Exception {


        boolean isStart=true;//該變量建議設置爲全局控制變量,用於控制錄製結束
        // 獲取視頻源
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        // 流媒體輸出地址,分辨率(長,高),是否錄製音頻(0:不錄製/1:錄製)
        FFmpegFrameRecorder recorder=new FFmpegFrameRecorder(outputFile,1280,720,audioChannel);
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,編碼
//                        recorder.setFormat("flv");
        recorder.setFormat("flv");//封裝格式,如果是推送到rtmp就必須是flv封裝格式
        recorder.setPixelFormat(0);
        recorder.setFrameRate(25);

        recorder.setVideoOption("preset", "ultrafast");
        recorder.setVideoOption("tune", "zerolatency");
        recorder.setVideoOption("fflags", "nobuffer");
        recorder.setVideoOption("analyzeduration", "0");
        // 開始取視頻源
        mapParas.put("s",true);
        recordByFrame(grabber, recorder);


    }

    public static Mat bufferedImageToMat(BufferedImage bi) {
        Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3);
        byte[] data = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
        mat.put(0, 0, data);
        return mat;
    }
    public void recordByFrame(FFmpegFrameGrabber grabber,FFmpegFrameRecorder recorder) throws Exception{
        //javacv提供的轉換器,方便mat轉換爲Frame
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        final Java2DFrameConverter frameConverter = new Java2DFrameConverter();        try{
            grabber.start();
            recorder.start();
            Frame frame=null;
            boolean status=(Boolean) mapParas.get("s");
            int index=0;

            //--在幀上面添加文字。
            CvFont font = new CvFont();
            cvInitFont(font, CV_FONT_HERSHEY_PLAIN, 2.0, 2.0, 2, 2, CV_AA);
            String logoText="我打了水印";//水印文字
            // 水印文字位置
            org.bytedeco.opencv.opencv_core.Point point = new Point(10, 50);
            // 顏色,使用黃色
            Scalar scalar = new Scalar(0, 255, 255, 0);

            OpenCVFrameConverter.ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage();
            Java2DFrameConverter java2dConverter = new Java2DFrameConverter();


            while(status&&(frame=grabber.grab())!=null&&!Thread.interrupted()){
                final BufferedImage bufferedImage = frameConverter.convert(frame);

                //--畫面合成
                if(bufferedImage!=null){
                    mark(bufferedImage,logoText,Color.RED,40,50);
                    IplImage iplImage = iplConverter.convert(java2dConverter.convert(bufferedImage));
//                cvPutText(iplImage/*IplImage*/, logoText, opencv_core.cvPoint(10,50),
//                        font,
//                        CvScalar.RED);
                    /***
                     * bufferedImage 轉換爲 mat 以便進行圖形操作
                     * **/

//                Mat newMat = bufferedImageToMat(bufferedImage);
                    /**添加文字上去**/

//                IplImage bgrImage = IplImage.create(frame.imageWidth, frame.imageHeight,IPL_DEPTH_8U, 3);;

                    index++;
                    System.out.println("第幾幀了:"+index);



                    if(iplImage!=null){
                        //--錄入畫面
                        recorder.record(converter.convert(iplImage));
                    }


                }

                if(frame.samples!=null){
                    //--錄入聲音
                    recorder.recordSamples(frame.samples);
                }

                //--如果不需要對畫面和聲音做合成,直接用record(frame)即可。
            }
            System.out.println("結束了,進行相關收尾。");
            grabber.stop();
            grabber.release();
            recorder.stop();
            recorder.release();

        }
        catch (Exception ed){
            ed.printStackTrace();
        }
        finally {
            if(grabber!=null){
                grabber.stop();
                grabber.release();
            }
            if(recorder!=null){
                recorder.stop();
                recorder.release();
            }
        }
    }


    // 加文字水印
    public void mark(BufferedImage bufImg, Image img, String text, Font font, Color color, int x, int y) {
        Graphics2D g = bufImg.createGraphics();
        g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
        g.setColor(color);
        g.setFont(font);
        g.drawString(text, x, y);
        g.dispose();
    }
    // 加文字水印
    public void mark(BufferedImage bufImg,  String text, Color color, int x, int y) {
        Graphics2D g = bufImg.createGraphics();
        Font currentFont = g.getFont();
        Font newFont = currentFont.deriveFont(currentFont.getSize() * 2F);
        g.setFont(newFont);

        g.setColor(color);
        g.drawString(text, x, y);
        g.dispose();
    }


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

        /**
         * 本次內容實現了,普通視頻-》推送到直播流
         * 直播流-》保存到本地
         * 直播流-》轉推其他直播流
         * **/
        Lesson03 test=new Lesson03();
        final String inputFile="/home/too-white/temp/a02.mp4";
        final String outFile="/home/too-white/temp/lesson03_output.flv";
        final String rtmpUrl="rtmp://localhost/live/livestream";
        /**
         * 推薦使用的rtmp直播平臺
         * https://blog.csdn.net/zhichaosong/article/details/89053009
         * **/
        final String rtmpOnlineUrl="rtmp://202.69.69.180:443/webcast/bshdlive-pc";


//        test.frameRecord(inputFile,outFile,1);
//        test.frameRecord(inputFile,rtmpUrl,1);
//        test.frameRecord(rtmpOnlineUrl,outFile,1);
        test.frameRecord(rtmpOnlineUrl,rtmpUrl,1);

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章