Unity3d 实现直播功能(无需sdk接入)

news2024/11/16 18:43:26

Unity3d 实现直播功能

需要插件 :VideoCapture 插件地址(免费的就行)
原理:客户端通过 VideoCapture 插件实现推流+nodejs视频流转服务进行转发,播放器实现rtmp拉流
废话不多说,直接上
场景对象挂上VideoCapture组件

CaptureSource我选择的是屏幕录制,也可以是其他源
CaptureType选择LIVE–直播形式
LiveStreamUrl选择自己本地服务地址 例如 rtmp://localhost:1935/live/unity//localhost也可以切换外网推流服务器地址

推流服务器

//  index.js 
const NodeMediaServer = require('node-media-server');
 
const config = {
  rtmp: {
    port: 1935,//rtmp服务端口号
    chunk_size: 60000,
    gop_cache: true,
    ping: 30,
    ping_timeout: 60
  },
  http: {
    port: 8000,//http服务端口号,拉流用的
    allow_origin: '*'
  }
};
 
var nms = new NodeMediaServer(config)
nms.run();

一个简单的nodejs服务,需提前安装依赖包

npm install node-media-server --save

安装完成后,命令行进入到 index.js所在目录执行

node index.js

命令,看到下图即为成功

服务运行成功
运行unity项目,点击 StartCapture

开启直播
打开拉流软件VLC(下载地址)
效果如下:
运行效果

视频效果如下

unity视频直播效果

unity直接起本地推流拉流服务代码(Editor使用,出包需要改地址和配合拷贝文件)


using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using UnityEngine;
//Editor完美运行,出包需要另外设置地址杀死nodejs推流程序
public class StartNodeJsServer : MonoBehaviour
{
    private void Start()
    {
        StartServer();
    }
    public void StartServer()
    {
        // create the command-line process
        var cmdProcess = new Process
        {
            StartInfo =
            {
                FileName = "cmd.exe",
                UseShellExecute = false,
                CreateNoWindow = true, // this is probably optional
                ErrorDialog = false, // this is probably optional
                RedirectStandardOutput = true,
                RedirectStandardInput = true
            }
        };

        // register for the output (for reading the output)
        cmdProcess.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
        {
            string output = e.Data;
            // inspect the output text here ...
        };

        // start the cmd process
        cmdProcess.Start();
        cmdProcess.BeginOutputReadLine();

        // execute your command
        //cmdProcess.StandardInput.WriteLine("npm install node-media-server --save");//服务器文件放到Assets目录下面的server内,出包的时候此处需要修改
        cmdProcess.StandardInput.WriteLine("node " + Application.dataPath + "/server/index.js");
        UnityEngine.Debug.LogError("node " + Application.dataPath + "/server/index.js");
        GameManager.Instance.nodeServerStarted = true;
    }

    public dynamic RunCmd(string cmd, bool isReturnStreamReader = false)
    {
        Process pro = new Process();
        pro.StartInfo.FileName = "cmd.exe";

        pro.StartInfo.CreateNoWindow = true;         // 不创建新窗口    
        pro.StartInfo.UseShellExecute = false;       //不启用shell启动进程  
        pro.StartInfo.RedirectStandardInput = true;  // 重定向输入    
        pro.StartInfo.RedirectStandardOutput = true; // 重定向标准输出    
        pro.StartInfo.RedirectStandardError = true;
        pro.StartInfo.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8;
        pro.StartInfo.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8;
        // 重定向错误输出  
        // pro.StartInfo.WorkingDirectory = path;
        pro.Start();//开启cmd
        pro.StandardInput.WriteLine(cmd);
        pro.StandardInput.AutoFlush = true;
        pro.StandardInput.WriteLine("exit"); //若是运行时间短可加入此命令

        dynamic output;
        if (isReturnStreamReader)
        {
            output = pro.StandardOutput;
        }
        else
        {
            output = pro.StandardOutput.ReadToEnd();
        }

        pro.WaitForExit();//若运行时间长,使用这个,等待程序执行完退出进程
        pro.Close();
        return output;
    }

    public List<string> GetPidOfAddress(string address)
    {
        //用来保存所有对应地址的端口号数据
        List<string> valueList = new List<string>();
        //获取返回的StreamReader数据
        StreamReader sr = RunCmd($"netstat -aon|findstr {address}", true);
        //读取StreamReader的每一行数据
        while (!sr.EndOfStream)
        {
            string value = sr.ReadLine();
            //查看当前读取的行中内容是否包含TCP字符
            if (!string.IsNullOrEmpty(value) && value.Contains("TCP"))
            {
                //只获取状态为 LISTENING 的数据
                string[] ss = value.Split("LISTENING");
                //获取端口号数据信息
                if (ss.Length >= 2)
                {
                    string port = ss[ss.Length - 1].Trim();
                    //重复的端口号不加入结果列表中
                    if (valueList.FirstOrDefault(a => a == port) == null)
                        valueList.Add(port);
                }
            }
        }
        return valueList;
    }

    /// <summary>
    /// 根据PID杀死对应进程
    /// </summary>
    /// <param name="pid"></param>
    /// <returns></returns>
    public string KillTask(string pid)
    {
        return RunCmd($"taskkill /F /pid {pid}");
    }

    private void OnApplicationQuit()//退出程序杀死直播服务
    {
        List<string> address = GetPidOfAddress("1935");
        address.ForEach((s) =>
        {
            KillTask(s);
        });
    }
}

网页查看视频效果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<script src="https://cdn.bootcss.com/flv.js/1.4.0/flv.min.js"></script>
		<video id="videoElement" style="width: 100%;" controls="controls"></video>
		<script>
		    if (flvjs.isSupported()) {
		        var videoElement = document.getElementById('videoElement');
		        var flvPlayer = flvjs.createPlayer({
		            type: 'flv',
					url:'http://localhost:8000/live/unity.flv' //这里走的http拉视频,所以用端口号8000
		        });
		        flvPlayer.attachMediaElement(videoElement);
		        flvPlayer.load();
		        flvPlayer.play();
		    }
		</script>
	</body>
</html>

参考链接(感谢大神铺路)
node.js简易版直播功能(局域网内)
Unity3d C#实现将场景中摄像头画面进行采集、录制并上传视频流(推流rtmp)直播的功能(含源码)

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

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

相关文章

【面试高频算法解析】算法练习2 回溯(Backtracking)

前言 本专栏旨在通过分类学习算法&#xff0c;使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目&#xff0c;帮助您深度理解每种算法&#xff0c;避免出现刷了很多算法题&#xff0c;还是一知半解的状态 专栏导航 二分查找回溯&#xff08;Backtracking&…

苹果QQ群聊天记录怎么删除?收藏好这两个技巧!

无论我们使用什么手机&#xff0c;我们都可以在QQ上与好友进行交流和社交。然而&#xff0c;有时候我们可能需要删除一些不需要的聊天记录&#xff0c;特别是群聊记录&#xff0c;以此来扩大手机内存。那么&#xff0c;苹果手机的qq群聊天记录怎么删除呢&#xff1f;小编将为大…

电子学会C/C++编程等级考试2023年12月(一级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:数的输入和输出 输入一个整数和双精度浮点数,先将浮点数保留2位小数输出,然后输出整数。 时间限制:1000 内存限制:65536 输入 一行两个数,分别为整数N(不超过整型范围),双精度浮点数F,以一个空格分开。 输出 一行两个数,分…

使用 C# 和 WinForms 创建动态图表

使用 C# 和 WinForms 创建动态图表 这次我们将学习如何使用 C# 和 WinForms 创建动态图表。我们将使用 Chart 控件来创建图表&#xff0c;并使用多线程技术实现动态更新图表数据的效果。 方法一&#xff1a;在项目启动时实例化图表 在 DoWork 方法中&#xff0c;我们使用 Ra…

宝塔上的琉璃灯(for循环试炼)

8层宝塔上共有765盏琉璃灯&#xff0c;每层灯数都是上层的一倍&#xff0c;编程输出每层灯数。 (笔记模板由python脚本于2024年01月09日 16:41:22创建&#xff0c;本篇笔记适合熟悉循环编程的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python…

【教程】代码混淆详解

目录 引言 正文 什么是代码混淆 ProGuard混淆文件参数详解 代码混淆的方法 Ipa Guard工具的使用方法 IPA重签名与安装测试 总结 本文将对代码混淆进行详细解释&#xff0c;并介绍ProGuard代码混淆器以及Ipa Guard工具的使用方法。首先&#xff0c;我们将了解代码混淆的概…

ORPC-824,对标可替代ACPL-824/PC824等

提供隔离反馈 逻辑电路之间的接口 电平转换 DC和AC输入 SMPS中的调节反馈电路 消除接地环路 特征 电流传输比 &#xff08; CTR &#xff1a; 最低 20% 在 IF 1mA&#xff0c; VCE 5V &#xff09; 宽工作温度范围 -55~110C 高输入输出隔离电压 &#xff08; Viso 5&am…

【算法设计与分析】网络流

目录 max-flow 和 min-cut流网络 Flow network最小割 Min-cut最大流 Max-flow Greedy algorithmFord–Fulkerson algorithm剩余网络 Residual networkFord–Fulkerson algorithm算法流程 最大流最小割理论 max-flow min-cut theorem容量扩展算法 capacity-scaling algorithm时间…

leetcode 每日一题 2024年01月09日 字符串中的额外字符

题目 字符串中的额外字符 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串&#xff0c;每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。 请你采取最优策略分割 s &…

解决命令行无法启动scrapy爬虫

前言 最近在准备毕设项目&#xff0c;想使用scrapy架构来进行爬虫&#xff0c;找了一个之前写过的样例&#xff0c;没想到在用普通的启动命令时报错。报错如下 无法将“scrapy”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径…

【AI】AI和点云(1/2)

目录 一、什么是点云 二、点云的应用领域 三、点云的创建 四、点云感知 一、什么是点云 在三维技术领域中&#xff0c;点云被定义为一种数据结构&#xff0c;用于表示三维空间中一组离散的点。这些点通常由它们的坐标&#xff08;x&#xff0c;y&#xff0c;z&#xff09;…

全视通以“物联数据中台+边缘信息化”,建设“三位一体”智慧医院

随着医疗信息化的不断深入&#xff0c;智慧医院已经成为医疗行业的发展方向。智慧医院是指利用信息技术和物联网技术&#xff0c;实现医疗服务、医疗管理和医疗保障的高效协同&#xff0c;提高医疗质量和安全&#xff0c;降低医疗成本&#xff0c;满足患者和医务人员的需求&…

Java_Swing程序设计

swing组件允许编程人员在跨平台时指定统一的外观和风格。 Swing组件通常被称为轻量级组件&#xff0c; JFrame在程序中的语法格式&#xff1a; JFrame jfnew JFrame(title); Container containerjf.getContentPane(); jf:JFrame类的对象 container:Container类的对象。 J…

Flutter - Android 安卓 消息推送FireBase notification 手机状态栏图标不显示或 白板、白底问题。

一、问题&#xff1a; 使用flutterfirebase 开发进行消息推送时&#xff0c;安卓真机推送消息 状态栏的图标显示白色方块。 二、原因&#xff1a; 从Android 5.0&#xff08;Lollipop&#xff09;开始&#xff0c;随着Material Design的引入&#xff0c;Android的设计语言和U…

单因素方差分析--R

任务说明 三个剂量水平的药物处理受试者&#xff0c;每个剂量水平十个受试者&#xff0c;现在收集到数据后&#xff0c;问&#xff1a; 药物剂量水平显著影响受试者的response&#xff1f; 或者不同剂量药物处理受试者有显著效果的差异吗&#xff1f; 数据 library(tidyvers…

c JPEG编码,但有错误

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> //v4l2 头文件 #include <strin…

3. SPSS数据文件的基本加工和处理

如何获取SPSS自带的案例数据文件&#xff1f; 首先找到SPSS的安装目录&#xff0c;然后找到Samples文件夹 可以看到有不同语言版本&#xff0c;选择简体中文 就能看到很多.sav文件 数据文件的整理 个案排序 单值排序 例&#xff1a;对于下面的数据集&#xff0c;将工资按…

拼多多API:从数据中挖掘商业价值的力量

随着大数据时代的来临&#xff0c;数据已经成为企业决策和创新的基石。拼多多API作为电商领域的重要接口&#xff0c;为企业提供了从数据中挖掘商业价值的机会。通过拼多多API&#xff0c;企业可以获取丰富的用户数据、商品数据和交易数据&#xff0c;从而深入了解市场需求、优…

【leetcode】字符串中的第一个唯一字符

题目描述 给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;则返回 -1 。 用例 示例 1&#xff1a; 输入: s “leetcode” 输出: 0 示例 2: 输入: s “loveleetcode” 输出: 2 示例 3: 输入: s “aabb”…

Flink CDC使用

Flink 环境准备 Flink 版本对应的CDC版本 两个jar包上传到flink bin目录下 flink-sql-connector-mysql-cdc mysql-connector-java 重启Flink集群