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

2024-01-08 20:02:12

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)直播的功能(含源码)

文章来源:https://blog.csdn.net/u014678046/article/details/135460445
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。