获取视频 RTMP 推流web播放

news2025/2/23 19:53:06

工作需要研究下市面上显示实时视频方案。这里介绍下RTMP协议。

需求获取USB摄像头,手机谁摄像头。显示到web网页上。

一、 采集摄像头

这个使用opencvSharp来采集:

nuget:

 

 var task = Task.Run(() =>
            {

                var capture = new VideoCapture(0);
                VideoCaptureProperties captureProperties = new VideoCaptureProperties();

                capture.Fps = 30;

                //苹果测试流
                //var capture = new VideoCapture("http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8", VideoCaptureAPIs.FFMPEG);
                if (!capture.IsOpened())
                {
                    ShowContent("Failed to open capture");
                    return;
                }

                //capture.Set(captureProperties, 80);

                var frame = new Mat();
                var process = new Process();
                while (true)
                {
                    capture.Read(frame);
                    if (frame.Size().Width > 0 && frame.Size().Height > 0)
                    {
                        HersheyFonts fontFace = new HersheyFonts();
                        frame.PutText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), new OpenCvSharp.Point(10, 30), fontFace, 1.0, Scalar.Red);
                        //var buffer = frame.ToBytes();
                        //byte[] bytes = frame.ToBytes(".jpg");
                        #region 压缩尺寸变小
                        //Cv2.Resize(frame, frame, new OpenCvSharp.Size(frame.Width / 2, frame.Height / 2));
                        byte[] bytes = CompressImEncode(frame); //CompressImEncodeNew(frame); //
                        //预览压缩
                        frame = Mat.FromImageData(bytes);

                        #endregion
                        MatToBitmapShow(frame);

                        MemoryStream memory = new MemoryStream();
                        memory.Write(bytes, 0, bytes.Length);
                        memory.Write(_delimiter, 0, _delimiter.Length);
                        SendTCP(memory.ToArray());
                        //Cv2.ImShow("Video", frame);
                        //Cv2.WaitKey(1);
                        // 延时一段时间
                        Cv2.WaitKey(1);
                    }
                }
            });

二、 准备RTMP 流服务器 

 这里使用 nginx-rtmp-http-flv

worker_processes  1;

events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1935;

        application live {
            live on;
            ##打开 GOP 缓存,减少首屏等待时间
            gop_cache on ; #打开GOP缓存,减少首屏等待时间
            record_max_size 1K; #设置录制文件的最大值。
            

        }
    }
}

#推流地址:rtmp://192.168.1.194:1935/live/video1
#FLV 播放地址:http://127.0.0.1:8088/flv?port=1935&app=live&stream=video1

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       8088;
        server_name  localhost;

        location / {
            add_header 'Access-Control-Allow-Origin' '*';
            root html;
            index  index.html index.htm;
        }

        location /live {
            flv_live on;
        }

        location /flv {
            add_header 'Access-Control-Allow-Origin' '*';
            flv_live on;
            chunked_transfer_encoding on;
        }
        
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

写推流到流媒体服务器:

string rtmp1 = "rtmp://127.0.0.1:1935/live/video1";
            string rtmp2 = "rtmp://127.0.0.1/live/test110";

            task = Task.Run(() =>
            {
                // 初始化 FFmpeg 库
                var capture = new VideoCapture(0);
                //var capture = new VideoCapture("http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8", VideoCaptureAPIs.FFMPEG);
                if (!capture.IsOpened())
                {
                    ShowContent("Failed to open capture");
                    return;
                }

                var frame = new Mat();
                var process = new Process();
                process.StartInfo.FileName = "ffmpeg";
                //aac 音频 -r 25 帧率25 -acodec aac
                process.StartInfo.Arguments = "-re -i - -vcodec libx264  -f flv " + rtmp1;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardInput = true;
                //下面这设置使其后台运行
                process.StartInfo.CreateNoWindow = true;

                process.Start();

                while (true)
                {
                    capture.Read(frame);
                    if (frame.Size().Width > 0 && frame.Size().Height > 0)
                    {
                        HersheyFonts fontFace = new HersheyFonts();
                        frame.PutText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), new OpenCvSharp.Point(10, 30), fontFace, 1.0, Scalar.Red);
                        var buffer = frame.ToBytes();

                        process.StandardInput.BaseStream.Write(buffer, 0, buffer.Length);
                        MatToBitmapShow(frame);
                        //Cv2.ImShow("Video", frame);
                        //Cv2.WaitKey(1);
                    }
                }
                process.WaitForExit();
            });

三、网页播放:

效果:

 

<!DOCTYPE html><html><head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <title>flv.js demo</title>
    <style>
        .mainContainer {            display: block;            width: 1024px;            margin-left: auto;            margin-right: auto;
        }        .urlInput {            display: block;            width: 100%;            margin-left: auto;            margin-right: auto;            margin-top: 8px;            margin-bottom: 8px;
        }        .centeredVideo {            display: block;            width: 100%;            height: 576px;            margin-left: auto;            margin-right: auto;            margin-bottom: auto;
        }        .controls {            display: block;            width: 100%;            text-align: left;            margin-left: auto;            margin-right: auto;
        }    
        
        </style>
        </head>
        
        <body>

            <h1>FLV </h1>
    <div class="mainContainer">
        <video id="videoElement" class="centeredVideo" controls autoplay width="1024" height="576">Your browser is too old which doesn't support HTML5 video.</video>
    </div>
    <br>
    <div class="controls">
        <!--<button onclick="flv_load()">加载</button>-->
        <button onclick="flv_start()">开始</button>
        <button onclick="flv_pause()">暂停</button>
        <button onclick="flv_destroy()">停止</button>
        <input style="width:100px" type="text" name="seekpoint" />
        <button onclick="flv_seekto()">跳转</button>
    </div>
    <script src="flv.min.js"></script>
    <script>
        var player = document.getElementById('videoElement');       
         if (flvjs.isSupported()) {         
               var flvPlayer = flvjs.createPlayer({          
                      type: 'flv',            
                          "isLive": true,//<====加个这个 
                    url: 'http://192.168.1.194:8088/flv?port=1935&app=live&stream=video1',//<==自行修改
                    
                    //url: 'http://127.0.0.1:8080/live/test110.flv',
            });
        flvPlayer.attachMediaElement(videoElement);
            flvPlayer.load(); //加载
            flv_start();
        }       
         function flv_start() {
            player.play();
        }        
        function flv_pause() {
            player.pause();
        }      
          function flv_destroy() {
            player.pause();
            player.unload();
            player.detachMediaElement();
            player.destroy();
            player = null;
        }      
        function flv_seekto() {
            player.currentTime = parseFloat(document.getElementsByName('seekpoint')[0].value);
        }   

        $(function(){
            flv_start();
        });

        // setInterval(() => {
        //     if (this.player.buffered.length) {
        //         let end = this.player.buffered.end(0);//获取当前buffered值
        //         let diff = end - this.player.currentTime;//获取buffered与currentTime的差值
        //         if (diff >= 0.5) {//如果差值大于等于0.5 手动跳帧 这里可根据自身需求来定
        //         this.player.currentTime = this.player.buffered.end(0);//手动跳帧
        //     }
        //     }
        // }, 2000); //2000毫秒执行一次  

         </script>
         
        </body>
         </html>

未完待续。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/729486.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP实战开发25-电商网站系统缓存设计方案系统讲述

文章目录 一、前言-缓存的作用1.1 提高性能1.2 减轻服务端压力1.3 减少网络流量1.4 改善用户体验1.5 支持离线访问1.6 降低数据传输成本 二、浏览器缓存2.1 强缓存2.2 协商缓存 三、CDN 缓存3.1 使用CDN缓存的好处3.1.1 加速网站加载时间3.1.2 节省服务器带宽3.1.3 提高可用性和…

快速计算多项式相乘系数 FFT快速傅里叶变换

快速计算多项式相乘系数 FFT快速傅里叶变换 快速傅里叶变换(FFT)——有史以来最巧妙的算法&#xff1f; 正常求两个多项式乘积 A ( x ) ∑ i 0 n A i x i , B ( x ) ∑ i 0 n B i x i C ( x ) ∑ i 0 n ∑ j 0 n A i B j x i j A(x)\sum_{i0}^{n}{A_ix^i},B(x)\sum_{…

Java多线程基础-11:工厂模式及代码案例之线程池

在Java中&#xff0c;xx池的概念是很常见的&#xff0c;比如之前遇到过的常量池、数据库连接池等等。 线程池是一种常用的多线程处理方式&#xff0c;它可以重复利用已创建的线程&#xff0c;从而减少线程的创建和销毁开销&#xff0c;并提高程序的性能。 通俗来说&#xff…

【Windows】Redis集群部署

集群是如何进行工作的 Redis采用哈希槽来处理数据与节点之间的映射关系&#xff0c;一个集群共有16384 个哈希槽&#xff0c;每个key通过 CRC16算法计算出一个16bit的值&#xff0c;再对16384取模&#xff0c;得到对应的哈希槽&#xff0c;集群通过维护哈希槽与节点的关系来得…

flutter聊天界面-Text富文本表情emoji、url、号码展示

flutter聊天界面-Text富文本表情emoji、url、号码展示 Text富文本表情emoji展示&#xff0c;主要通过实现Text.rich展示文本、emoji、自定义表情、URL等 一、Text及TextSpan Text用于显示简单样式文本 TextSpan它代表文本的一个“片段”&#xff0c;不同“片段”可按照不同的…

Verilog学习笔记2:反相器

代码&#xff1a; //反相器 timescale 1ns/10ps module inv( A,y); input A; output y; assign y~A; endmodule //testbench module inv_tb;reg A; wire YY;inv inv(.A(A),.y(YY));initial beginA<0;#10 A<1;#10 A<0; #10 A<1;#10 A<0; #10 A<1;#10 A<0;…

从小白到大神之路之学习运维第54天--------ELK日志收集分析

第三阶段基础 时 间&#xff1a;2023年7月6日 地 点&#xff1a;2304教室 授课人&#xff1a;李凤海 参加人&#xff1a;全班人员 内 容&#xff1a; ELK技术堆栈 目录 服务器设置&#xff1a; 部署elasticsearch集群&#xff1a; 配置elasticsearch集群&#xff…

怎样寻找SEO服务商,需要注意那些问题?

网上提供SEO服务的公司或个人多如牛毛&#xff0c;随便在搜索引擎上搜索一下&#xff0c;成千上万的公司就在眼前。大部分网站设计公司也兼职SEO服务&#xff0c;寻找合适的SEO服务商并不简单&#xff0c;鉴别合格的SEO服务商是关键。 1、确定外包任务 如果没有SEO团队&…

C++类相关概念

1. 函数形参默认值 &#xff08;1&#xff09; 建议函数&#xff08;不仅仅是构造函数&#xff09;形参默认值只在函数声明中指定&#xff1b; &#xff08;函数声明和定义写在同一个文件中&#xff0c;则函数声明、定义两者之一或两者都可指定形参默认值&#xff0c;两者都指定…

mybati执行流程源码分析

MyBatis执行流程源码分析 前言 由于之前写过关于mybatis源码的文章,但是感觉还是不够细致,不够完善.没有把一些具体的流程应用写下来,至此又写了一篇.内容可能比较长,希望大家可以打开源码跟着这篇文章一起看源码保证可以收获许多. 1.mybatis基础开发流程 1.引入mybatis相关…

短视频去水印小帮手微信小程序源码带后台

短视频去水印小帮手微信​小程序源码​带后台&#xff0c;短视频去水印系列教程服务端源码。 php版&#xff0c;这里不过多介绍&#xff0c;我假设您有基本的编码基础&#xff0c;并熟悉php语言及laravel框架。

Topaz Gigapixel AI v6 人工智能图像放大

其他软件或插件依赖于插值算法来放大图像&#xff0c;Topaz Gigapixel AI 则与众不同&#xff0c;它使用最先进的深度学习技术来扩大和增强图像。 它通过神经网络分析了数百万张照片&#xff0c;从而了解了不同的照片在放大时细节是如何损失的&#xff0c;以及如何为图像增强和…

四十三、贪心——Huffman树、排序不等式

算法主要内容 一、Huffman树1、题目内容——合并果子2、算法思路&#xff08;1&#xff09;“合并果子”中的Huffman树&#xff08;2&#xff09;算法步骤&#xff08;3&#xff09;状态转移 3、题解 二、排序不等式1、题目内容——排队打水2、算法思路&#xff08;1&#xff0…

【MySQL】数据库基础概念

文章目录 前言连接服务器什么是数据库&#xff1f;MySQL和MySQLdLinux中如何看到数据库文件SQL语句分类存储引擎 前言 今天继续讲解MySQL相关内容&#xff0c;本期主要讲解数据库的基础概念&#xff0c;方便后续学习数据库。 连接服务器 mysql -h [ip] -P [port] -u [root] …

IRIS在Linux下通过JDBC操作其他数据库

以前都是在Windows上用cache的SqlGateway通过odbc创建连接操作其他数据库。现在都用Linux了&#xff0c;那么和其他数据进行调用咋办呢。 可以看到是可以创建JDBC的连接的&#xff0c;而Java是跨平台的&#xff0c;所以可以用JDBC操作其他数据库&#xff0c;这次以mysql为例。…

浅谈Node.js中的npm和yarn

官方文档&#xff1a; npmhttps://www.npmjs.cn/ yarnhttps://yarn.bootcss.com/ npm和yarn的作用 yarn和npm都是构建和打包javascript代码的工具 区别 npm&#xff1a; 1npm使得js开发者易于分享其为解决特定问题而编写的代码&#xff0c;且可供其他开发者在他们自己的应…

【阶段学习小总结】

串口通信和CAN总线通信的区别 can总线和串口是两种不同的通信模式&#xff0c;注意CAN总线数据传输所用的虽然是DB9串口线&#xff0c;但它完全不是串口&#xff0c;这一点容易出错。 CAN总线通信是高速&#xff0c;可靠&#xff0c;灵活的一种通信协议。作为一种分布式通信方…

天梯赛注意事项

格式错误 有的时候题目隐含的条件是要你输出两行的&#xff0c;即使第二行什么也没有&#xff0c;也得输出。 答案错误可能涉及特殊值的处理 或者 题意与你本身的思维不一致 map定义在main外面 键自动赋值 it->first it->second mp自动按照下标排序 . 模拟出栈入栈操…

使用GTK创建简易计算器

使用GTK创建简易计算器 本文将介绍如何使用GTK&#xff08;GIMP Toolkit&#xff09;创建一个简单的计算器应用程序。通过这个例子&#xff0c;你将学习如何构建基本的图形用户界面&#xff0c;并了解GTK的一些常用组件和回调函数的使用。 准备工作 首先&#xff0c;确保你已…

Django之中间件

一、中间件介绍 官方的说法&#xff1a;中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统&#xff0c;用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。 但是由于其影响的是全局&#xff0c;所以需要…