Unity3d 使用Unity将视频传输到YouTube流媒体API V3
我正在尝试开发unity内部的实时流功能,目前我使用RTMP将视频传输到YouTube,我还使用FFmpeg编码器对MP4视频进行编码,并将其发送到RTMP服务器。我面临两个问题 1-视频在多次发送到RTMP服务器后显示在流上,可能需要10分钟。而流具有良好的数据连接 2-我已经能够连续发送静态MP4视频了如何实时编码和发送数据 3-我正在寻找更好的编码器,可以发送到RTMP服务器,并将与android/PC工作 欢迎任何有助于发展的建议Unity3d 使用Unity将视频传输到YouTube流媒体API V3,unity3d,youtube-api,video-streaming,streaming,youtube-data-api,Unity3d,Youtube Api,Video Streaming,Streaming,Youtube Data Api,我正在尝试开发unity内部的实时流功能,目前我使用RTMP将视频传输到YouTube,我还使用FFmpeg编码器对MP4视频进行编码,并将其发送到RTMP服务器。我面临两个问题 1-视频在多次发送到RTMP服务器后显示在流上,可能需要10分钟。而流具有良好的数据连接 2-我已经能够连续发送静态MP4视频了如何实时编码和发送数据 3-我正在寻找更好的编码器,可以发送到RTMP服务器,并将与android/PC工作 欢迎任何有助于发展的建议 { private Thread thread;
{
private Thread thread;
IEnumerator Start()
{
// GOOGLE API KEYS
var clientId = "";
var clientSecret = "";
var code = ""; // LEAVE IT
// Login and get the token
LocalServer(c => code = c);
var authUrl = "https://accounts.google.com/o/oauth2/v2/auth?response_type=code"
+ "&client_id=" + clientId
+ "&redirect_uri=" + "http://localhost:8080"
+ "&scope=" + "https://www.googleapis.com/auth/youtube.force-ssl"
+ "&access_type=" + "offline";
Application.OpenURL(authUrl);
yield return new WaitUntil(() => code != "");
// Debug.Log(code);
var tokenUrl = "https://www.googleapis.com/oauth2/v4/token";
var content = new Dictionary<string, string>() {
{ "code", code },
{ "client_id", clientId },
{ "client_secret", clientSecret },
{ "redirect_uri", "http://localhost:8080" },
{ "grant_type", "authorization_code" },
{ "access_type", "offline" },
};
var request = UnityWebRequest.Post(tokenUrl, content);
yield return request.SendWebRequest();
var json = JSON.Parse(request.downloadHandler.text);
var token = json["access_token"].RawString();
// Insert the live broadcast
var liveBroadCastURL = "https://www.googleapis.com/youtube/v3/liveBroadcasts?part=snippet%2CcontentDetails%2Cstatus";
// Create live broadcast json to send to the server
LiveBroadcast.Snippet liveBroadcastSnip = new LiveBroadcast.Snippet();
liveBroadcastSnip.title = "Sample broadcast";
liveBroadcastSnip.scheduledStartTime = "2020-01-29T10:07:48+0000";
liveBroadcastSnip.scheduledEndTime = "2020-01-29T10:07:48+0000";
LiveBroadcast.Status liveBroadcastState = new LiveBroadcast.Status();
liveBroadcastState.privacyStatus = "public";
liveBroadcastState.selfDeclaredMadeForKids = true;
LiveBroadcast.LiveBroadcastObject liveBroadcastData = new LiveBroadcast.LiveBroadcastObject();
liveBroadcastData.snippet = liveBroadcastSnip;
liveBroadcastData.status = liveBroadcastState;
var liveBroadcastRequest = new UnityWebRequest(liveBroadCastURL, "POST");
string broadcastData = JsonUtility.ToJson(liveBroadcastData);
byte[] broadcastBody = Encoding.UTF8.GetBytes(broadcastData);
liveBroadcastRequest.uploadHandler = new UploadHandlerRaw(broadcastBody);
liveBroadcastRequest.downloadHandler = new DownloadHandlerBuffer();
liveBroadcastRequest.SetRequestHeader("Authorization", "Bearer " + token);
liveBroadcastRequest.SetRequestHeader("Content-Type", "application/json");
yield return liveBroadcastRequest.SendWebRequest();
// server response and save created broadcast id
var broadcastJson = JSON.Parse(liveBroadcastRequest.downloadHandler.text);
var broadcastID = broadcastJson["id"].RawString();
UnityEngine.Debug.Log("Broadcast ID: " + broadcastID);
// Create live stream
var LiveStreamURL = "https://www.googleapis.com/youtube/v3/liveStreams?part=snippet%2Ccdn%2CcontentDetails%2Cstatus";
// Create live stream json to send to the server
LiveStream.Snippet liveStreamSnip = new LiveStream.Snippet();
liveStreamSnip.title = "Sample Test";
liveStreamSnip.description = "Hello My Video";
LiveStream.Cdn liveStreamCDN = new LiveStream.Cdn();
liveStreamCDN.frameRate = "60fps";
liveStreamCDN.ingestionType = "rtmp";
liveStreamCDN.resolution = "720p";
LiveStream.ContentDetails liveStreamDetails = new LiveStream.ContentDetails();
liveStreamDetails.isReusable = false;
LiveStream.LiveStreamObject liveStreamData = new LiveStream.LiveStreamObject();
liveStreamData.snippet = liveStreamSnip;
liveStreamData.cdn = liveStreamCDN;
liveStreamData.contentDetails = liveStreamDetails;
string streamData = JsonUtility.ToJson(liveStreamData);
var liveStreamRequest = new UnityWebRequest(LiveStreamURL, "POST");
byte[] streamBody = Encoding.UTF8.GetBytes(streamData);
liveStreamRequest.uploadHandler = new UploadHandlerRaw(streamBody);
liveStreamRequest.downloadHandler = new DownloadHandlerBuffer();
liveStreamRequest.SetRequestHeader("Authorization", "Bearer " + token);
liveStreamRequest.SetRequestHeader("Content-Type", "application/json");
yield return liveStreamRequest.SendWebRequest();
// server response and save created stream data
var streamJson = JSON.Parse(liveStreamRequest.downloadHandler.text);
var streamID = streamJson["id"].RawString();
var streamName = streamJson["cdn"]["ingestionInfo"]["streamName"].RawString();
var ingestionAddress = streamJson["cdn"]["ingestionInfo"]["ingestionAddress"].RawString();
UnityEngine.Debug.Log("Stream ID: "+ streamID);
UnityEngine.Debug.Log("Stream Name: " + streamName);
UnityEngine.Debug.Log("Ingestion Address: " + ingestionAddress);
// Bind the stream and broadcast
var bindUrl = "https://www.googleapis.com/youtube/v3/liveBroadcasts/bind";
var bindContent = new Dictionary<string, string>() {
{ "id", broadcastID },
{ "part", "snippet" },
{ "streamId", streamID },
};
var bindRequest = UnityWebRequest.Post(bindUrl, bindContent);
bindRequest.SetRequestHeader("Authorization", "Bearer " + token);
bindRequest.SetRequestHeader("Accept", "application/json");
yield return bindRequest.SendWebRequest();
var bindJson = JSON.Parse(bindRequest.downloadHandler.text);
var bindID = bindJson["id"].RawString(); // not importand or used
UnityEngine.Debug.Log("Bind ID: " + bindID);
Application.OpenURL("https://studio.youtube.com/channel/"+streamID+"/livestreaming/dashboard?v=" + broadcastID);
// Start the encoder
List<string> commands = new List<string>();
commands.Add(@"cd " + Application.dataPath + "/Resources/FFmpeg");
commands.Add("ffmpeg -re -i Sample.mp4 -c copy -f flv rtmp://a.rtmp.youtube.com/live2/" + streamName);
thread = new Thread(() => RunCommands(commands));
thread.Start();
}
void LocalServer(Action<string> onReceive)
{
ThreadStart start = () => {
try
{
var listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
var context = listener.GetContext();
var req = context.Request;
var res = context.Response;
var re = new Regex(@"/\?code=(?<c>.*)");
var code = re.Match(req.RawUrl).Groups["c"].ToString();
onReceive(code);
res.StatusCode = 200;
res.Close();
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e);
}
};
new Thread(start).Start();
}
public static void RunCommands(List<string> cmds, string workingDirectory = "")
{
var process = new Process();
var psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.RedirectStandardInput = true;
psi.CreateNoWindow = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
psi.WorkingDirectory = workingDirectory;
process.StartInfo = psi;
process.Start();
process.OutputDataReceived += (sender, e) => { UnityEngine.Debug.Log(e.Data); };
process.ErrorDataReceived += (sender, e) => { UnityEngine.Debug.Log(e.Data); };
process.BeginOutputReadLine();
process.BeginErrorReadLine();
using (StreamWriter sw = process.StandardInput)
{
foreach (var cmd in cmds)
{
sw.WriteLine(cmd);
}
}
process.WaitForExit();
RunCommands(cmds);
}
private void OnApplicationQuit()
{
thread.Abort();
}
}
public static class SimpleJsonUtility
{
public static string RawString(this JSONNode node)
{
var len = node.ToString().Length - 2;
return node.ToString().Substring(1, len);
}
}
{
私有线程;
IEnumerator Start()
{
//谷歌API密钥
var clientId=“”;
var clientSecret=“”;
var code=”“;//离开它
//登录并获取令牌
LocalServer(c=>code=c);
var authUrl=”https://accounts.google.com/o/oauth2/v2/auth?response_type=code"
+“&client_id=“+clientId
+“&重定向_uri=“+”http://localhost:8080"
+“&scope=“+”https://www.googleapis.com/auth/youtube.force-ssl"
+“&access_type=“+”脱机”;
Application.OpenURL(authUrl);
返回新的等待时间(()=>代码!=“”);
//调试日志(代码);
var tokenUrl=”https://www.googleapis.com/oauth2/v4/token";
var content=newdictionary(){
{“代码”,代码},
{“client_id”,clientId},
{“客户机密”,clientSecret},
{“重定向uri”http://localhost:8080" },
{“授权类型”、“授权代码”},
{“访问类型”,“脱机”},
};
var request=UnityWebRequest.Post(令牌URL,内容);
生成返回请求。SendWebRequest();
var json=json.Parse(request.downloadHandler.text);
var token=json[“访问令牌”].RawString();
//插入直播
var liveBroadCastURL=”https://www.googleapis.com/youtube/v3/liveBroadcasts?part=snippet%2CcontentDetails%2Cstatus";
//创建要发送到服务器的直播json
LiveBroadcast.Snippet liveBroadcastSnip=new LiveBroadcast.Snippet();
liveBroadcastSnip.title=“示例广播”;
liveBroadcastSnip.scheduledStartTime=“2020-01-29T10:07:48+0000”;
liveBroadcastSnip.scheduledEndTime=“2020-01-29T10:07:48+0000”;
LiveBroadcast.Status liveBroadcastState=新的LiveBroadcast.Status();
liveBroadcastState.privacyStatus=“public”;
liveBroadcastState.selfDeclaredMadeForKids=true;
LiveBroadcast.LiveBroadcastObject liveBroadcastData=新的LiveBroadcast.LiveBroadcastObject();
liveBroadcastData.snippet=liveBroadcastSnip;
liveBroadcastData.status=liveBroadcastState;
var liveBroadcastRequest=newunityWebRequest(liveBroadCastURL,“POST”);
string broadcastData=JsonUtility.ToJson(liveBroadcastData);
byte[]broadcastBody=Encoding.UTF8.GetBytes(broadcastData);
liveBroadcastRequest.uploadHandler=新的UploadHandlerRaw(broadcastBody);
liveBroadcastRequest.downloadHandler=新的DownloadHandlerBuffer();
SetRequestHeader(“授权”、“承载者”+令牌);
SetRequestHeader(“内容类型”、“应用程序/json”);
返回liveBroadcastRequest.SendWebRequest();
//服务器响应并保存创建的广播id
var broadcastJson=JSON.Parse(liveBroadcastRequest.downloadHandler.text);
var broadcastID=broadcastJson[“id”].RawString();
UnityEngine.Debug.Log(“广播ID:+broadcastID”);
//创建实时流
var LiveStreamURL=”https://www.googleapis.com/youtube/v3/liveStreams?part=snippet%2Ccdn%2CcontentDetails%2Cstatus";
//创建要发送到服务器的实时流json
LiveStream.Snippet liveStreamSnip=新的LiveStream.Snippet();
liveStreamSnip.title=“样本测试”;
liveStreamSnip.description=“你好,我的视频”;
LiveStream.Cdn liveStreamCDN=新的LiveStream.Cdn();
liveStreamCDN.frameRate=“60fps”;
liveStreamCDN.ingestionType=“rtmp”;
liveStreamCDN.resolution=“720p”;
LiveStream.ContentDetails liveStreamDetails=新的LiveStream.ContentDetails();
liveStreamDetails.isReusable=false;
LiveStream.LiveStreamObject liveStreamData=新的LiveStream.LiveStreamObject();
liveStreamData.snippet=liveStreamSnip;
liveStreamData.cdn=liveStreamCDN;
liveStreamData.contentDetails=liveStreamDetails;
string streamData=JsonUtility.ToJson(liveStreamData);
var liveStreamRequest=newunitywebrequest(LiveStreamURL,“POST”);
byte[]streamBody=Encoding.UTF8.GetBytes(streamData);
liveStreamRequest.uploadHandler=新的UploadHandlerRaw(streamBody);
liveStreamRequest.downloadHandler=新的DownloadHandlerBuffer();
SetRequestHeader(“授权”、“承载者”+令牌);
SetRequestHeader(“内容类型”、“应用程序/json”);
返回liveStreamRequest.SendWebRequest();
//服务器响应并保存创建的流数据
var streamJson=JSON.Parse(liveStreamRequest.downloadHandler.text);
var streamID=streamJson[“id”].RawString();
var streamName=streamJson[“cdn”][“ingestionInfo”][“streamName”].RawString();
var-ingestionAddress=streamJson[“cdn”][“ingestionInfo”][“ingestionAddress”].RawString();
UnityEngine.Debug.Log(“流ID:+streamID”);
UnityEngine.Debug.Log(“流名称:”+streamName);
UnityEngine.Debug.Log(“摄取地址:+ingestionAddress”);
//绑定流并广播
var bindUrl=”https://www.googleapis.com/youtube/v3/liveBroadcasts/bind";
var bindConten