public LiveBroadcast GenerateBroadCast() { //broadcast snippet contains basic info about the broadcast and this is shown on youtube when launched LiveBroadcastSnippet broadCastSnippet = new LiveBroadcastSnippet(); broadCastSnippet.Title = "Test"; broadCastSnippet.Description = "A test of the youtube data API"; //TODO: Add a thumbnail icon broadCastSnippet.ScheduledStartTime = DateTime.Now; //Applies settings of made for kids and unlisted to snippet i.e broadcast settings LiveBroadcastStatus broadCastStatus = new LiveBroadcastStatus(); broadCastStatus.SelfDeclaredMadeForKids = false; broadCastStatus.PrivacyStatus = "unlisted"; //enables the broadcast to view a different "special stream" in case of time delays etc good for debugging MonitorStreamInfo broadCastMonitorStream = new MonitorStreamInfo(); broadCastMonitorStream.EnableMonitorStream = true; //contains info about the monitor stream LiveBroadcastContentDetails broadCastContentDetails = new LiveBroadcastContentDetails(); broadCastContentDetails.MonitorStream = broadCastMonitorStream; LiveBroadcast broadCast = new LiveBroadcast(); broadCast.Snippet = broadCastSnippet; //binds the info regarding stream broadCast.Status = broadCastStatus; //privacy settings & reg settings broadCast.ContentDetails = broadCastContentDetails; //binds monitor info //Allows to finalise the setting up and is ready to be transmitted LiveBroadcastsResource.InsertRequest liveBroadCastInsert = service.LiveBroadcasts.Insert(broadCast, "snippet,status,contentDetails"); //Reads the returned var LiveBroadcast returnedBroadCast = liveBroadCastInsert.Execute(); Console.WriteLine("\n================== Returned Broadcast ==================\n"); Console.WriteLine(" - Id: " + returnedBroadCast.Id); Console.WriteLine(" - Title: " + returnedBroadCast.Snippet.Title); Console.WriteLine(" - Description: " + returnedBroadCast.Snippet.Description); Console.WriteLine(" - Published At: " + returnedBroadCast.Snippet.PublishedAt); Console.WriteLine( " - Scheduled Start Time: " + returnedBroadCast.Snippet.ScheduledStartTime); Console.WriteLine( " - Scheduled End Time: " + returnedBroadCast.Snippet.ScheduledEndTime); return(returnedBroadCast); }
public YoutubeApi() { service = Auth(); var broadcastSnippet = new LiveBroadcastSnippet(); broadcastSnippet.Title = "Biometrico"; broadcastSnippet.ScheduledStartTime = DateTime.Now; var broadcastStatus = new LiveBroadcastStatus(); broadcastStatus.PrivacyStatus = "unlisted"; var broadcastMonitorStream = new MonitorStreamInfo(); broadcastMonitorStream.EnableMonitorStream = true; var broadcastContentDetails = new LiveBroadcastContentDetails(); broadcastContentDetails.MonitorStream = broadcastMonitorStream; var broadcast = new LiveBroadcast(); broadcast.Kind = "youtube#liveBroadcast"; broadcast.Snippet = broadcastSnippet; broadcast.Status = broadcastStatus; broadcast.ContentDetails = broadcastContentDetails; var liveBroadcastInsert = service.LiveBroadcasts.Insert(broadcast, "snippet,status,contentDetails"); var returnedBroadcast = liveBroadcastInsert.Execute(); Console.WriteLine("\n================== Returned Broadcast ==================\n"); Console.WriteLine(" - Id: " + returnedBroadcast.Id); Console.WriteLine(" - Title: " + returnedBroadcast.Snippet.Title); Console.WriteLine(" - Description: " + returnedBroadcast.Snippet.Description); Console.WriteLine(" - Published At: " + returnedBroadcast.Snippet.PublishedAt); Console.WriteLine( " - Scheduled Start Time: " + returnedBroadcast.Snippet.ScheduledStartTime); Console.WriteLine( " - Scheduled End Time: " + returnedBroadcast.Snippet.ScheduledEndTime); var streamSnippet = new LiveStreamSnippet(); streamSnippet.Title = "Camara de Establecimiento"; var cdnSettings = new CdnSettings(); cdnSettings.Format = "720p"; cdnSettings.IngestionType = "rtmp"; var stream = new LiveStream(); stream.Kind = "youtube#liveStream"; stream.Snippet = streamSnippet; stream.Cdn = cdnSettings; var liveStreamInsert = service.LiveStreams.Insert(stream, "snippet,cdn"); var returnedStream = liveStreamInsert.Execute(); Console.WriteLine("\n================== Returned Stream ==================\n"); Console.WriteLine(" - Id: " + returnedStream.Id); Console.WriteLine(" - Title: " + returnedStream.Snippet.Title); Console.WriteLine(" - Description: " + returnedStream.Snippet.Description); Console.WriteLine(" - Published At: " + returnedStream.Snippet.PublishedAt); Console.WriteLine(" - URL: " + returnedStream.Cdn.IngestionInfo.IngestionAddress); Console.WriteLine(" - Name: " + returnedStream.Cdn.IngestionInfo.StreamName); var liveBroadcastBind = service.LiveBroadcasts.Bind(returnedBroadcast.Id, "id, contentDetails"); liveBroadcastBind.StreamId = returnedStream.Id; returnedBroadcast = liveBroadcastBind.Execute(); Console.WriteLine("\n================== Returned Bound Broadcast ==================\n"); Console.WriteLine(" - Broadcast Id: " + returnedBroadcast.Id); Console.WriteLine(" - Bound Stream Id: " + returnedBroadcast.ContentDetails.BoundStreamId); var liveStreamRequest = service.LiveStreams.List("id,status"); liveStreamRequest.Id = returnedStream.Id; string streamLoop = "0"; while (!streamLoop.Contains("A")) { var returnedStreamListResponse = liveStreamRequest.Execute(); var foundStream = returnedStreamListResponse.Items.Single(); Console.WriteLine(foundStream.Status.StreamStatus); streamLoop = Console.ReadKey().Key.ToString(); } returnedBroadcast.ContentDetails.MonitorStream.EnableMonitorStream = false; service.LiveBroadcasts.Update(returnedBroadcast, "contentDetails"); var liveBroadcastRequest = service.LiveBroadcasts.List("id,status,contentDetails"); liveBroadcastRequest.Id = returnedBroadcast.Id; char broadcastLoop = '0'; while (broadcastLoop != ('A')) { var returnedBroadcastListResponse = liveBroadcastRequest.Execute(); var foundBroadcast = returnedBroadcastListResponse.Items.Single(); Console.WriteLine(foundBroadcast.ContentDetails.MonitorStream.EnableMonitorStream); broadcastLoop = Console.ReadKey().KeyChar; } service.LiveBroadcasts.Transition(LiveBroadcastsResource.TransitionRequest.BroadcastStatusEnum.Testing, returnedBroadcast.Id, ""); broadcastLoop = '0'; while (broadcastLoop != 'A') { var returnedBroadcastListResponse = liveBroadcastRequest.Execute(); var foundBroadcast = returnedBroadcastListResponse.Items.Single(); Console.WriteLine(foundBroadcast.Status.LifeCycleStatus); broadcastLoop = Console.ReadKey().KeyChar; } service.LiveBroadcasts.Transition(LiveBroadcastsResource.TransitionRequest.BroadcastStatusEnum.Live, returnedBroadcast.Id, ""); broadcastLoop = '0'; while (broadcastLoop != ('A')) { var returnedBroadcastListResponse = liveBroadcastRequest.Execute(); var foundBroadcast = returnedBroadcastListResponse.Items.Single(); Console.WriteLine(foundBroadcast.Status.LifeCycleStatus); broadcastLoop = Console.ReadKey().KeyChar; } //rtsp://192.168.1.99/axis-media/media.amp }
IEnumerator StreamToYoutubeCoroutine() { float dt = .5f; //---OAuth2 Authorization #region setup OAuth2 Login with ClientId & ClientSecret Debug.Log("======OAuth2 Login Session Started======="); streamstatusLabel.text = "setup OAuth2 Login with ClientId & ClientSecret"; Task <UserCredential> taskGetUserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets { ClientId = Credentials.CLIENT_ID, ClientSecret = Credentials.CLIENT_SECRET }, new[] { YouTubeService.Scope.Youtube }, "user", CancellationToken.None); yield return(new WaitUntil(() => taskGetUserCredential.Status == TaskStatus.RanToCompletion)); UserCredential credential = taskGetUserCredential.Result; Debug.Log($"Login successful with {credential}"); Debug.Log("======OAuth2 Login Session Ended======="); var youtubeService = new YouTubeService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = APP_NAME }); Debug.Log($"Create Youtube Service with user credential {youtubeService.BaseUri}"); #endregion //---create LiveBroadCast #region setup LiveBroadCast Channel (LiveBroadcastSnippet) streamstatusLabel.text = "setup LiveBroadCast Channel"; Debug.Log("======create LiveBroadCast Started======="); // Create a snippet with the title and scheduled start and end // times for the broadcast. Currently, those times are hard-coded. LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet(); broadcastSnippet.Title = streamtitle; broadcastSnippet.PublishedAt = DateTime.Now; broadcastSnippet.ScheduledStartTime = DateTime.Now; broadcastSnippet.ScheduledEndTime = DateTime.Now.AddHours(2); Debug.Log($"Prepare LiveBroadCast Snippet with Title: {broadcastSnippet.Title}"); // Set the broadcast's privacy status to "private". See: // https://developers.google.com/youtube/v3/live/docs/liveBroadcasts#status.privacyStatus LiveBroadcastStatus status = new LiveBroadcastStatus(); status.PrivacyStatus = "public"; LiveBroadcast broadcast = new LiveBroadcast(); broadcast.Kind = "youtube#liveBroadcast"; broadcast.Snippet = broadcastSnippet; broadcast.Status = status; Debug.Log($"Prepare LiveBroadCast status: {status.LiveBroadcastPriority}"); LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails(); contentDetails.Projection = "360"; broadcast.ContentDetails = contentDetails; Debug.Log($"Try to insert LiveBroadcasts"); try { broadcast = youtubeService.LiveBroadcasts.Insert(broadcast, "snippet,status,contentDetails").Execute(); Debug.Log($"Insert LiveBroadcasts successfully with ID: {broadcast.Id}"); } catch (Exception e) { Debug.LogError(e); yield break; } Debug.Log("======create LiveBroadCast Ended======="); #endregion //---create streaming channel #region setup Streaming Channel (LiveStreamSnippet) streamstatusLabel.text = "setup Streaming Channel"; Debug.Log("======create Streaming channel Started======="); // Create a snippet with the video stream's title. LiveStreamSnippet streamSnippet = new LiveStreamSnippet(); streamSnippet.Title = streamtitle; Debug.Log($"Prepare streaming Snippet {streamSnippet.Title}"); IngestionInfo ingestionInfo = new IngestionInfo(); ingestionInfo.StreamName = streamname; //this Rtmp address is fixed ,defined by youtube API, //we need to get full push address by appending streaming ID. ingestionInfo.IngestionAddress = "rtmp://a.rtmp.youtube.com/live2"; // Define the content distribution network settings for the // video stream. The settings specify the stream's format and // ingestion type. See: // https://developers.google.com/youtube/v3/live/docs/liveStreams#cdn CdnSettings cdnSettings = new CdnSettings(); cdnSettings.IngestionInfo = ingestionInfo; cdnSettings.Format = "720p"; cdnSettings.IngestionType = "rtmp"; Debug.Log($"Prepare CDN settings type:{cdnSettings.IngestionType}"); LiveStream stream = new LiveStream(); stream.Kind = "youtube#liveStream"; stream.Snippet = streamSnippet; stream.Cdn = cdnSettings; // Construct and execute the API request to insert the stream. Debug.Log($"Try to insert LiveStreams"); LiveStream liveStream = null; try { liveStream = youtubeService.LiveStreams.Insert(stream, "snippet,cdn").Execute(); Debug.Log($"Open livestream successfully with Id {liveStream.Cdn.IngestionInfo.StreamName}"); } catch (Exception e) { Debug.LogError(e); yield break; } var push_addr = liveStream.Cdn.IngestionInfo.IngestionAddress + "/" + liveStream.Cdn.IngestionInfo.StreamName; Debug.Log($"Get rtmp push address: {push_addr}"); Debug.Log("======create Streaming channel Ended======="); #endregion //---bind LiveBroadcast & LiveStreams #region bind LiveBroadcast & LiveStreams streamstatusLabel.text = "bind LiveBroadcast & LiveStreams"; Debug.Log("======bind LiveBroadcast & LiveStreams Started======="); // Construct and execute a request to bind the new broadcast and stream. Debug.Log($"Try to bind LiveBroadcast and streams {broadcast.Id}"); LiveBroadcastsResource.BindRequest liveBroadcastBind = null; try { liveBroadcastBind = youtubeService.LiveBroadcasts.Bind(broadcast.Id, "id,contentDetails"); liveBroadcastBind.StreamId = liveStream.Id; broadcast = liveBroadcastBind.Execute(); Debug.Log($"Binding LiveBroadcasts and Streams successfully with Id {liveBroadcastBind.StreamId}"); } catch (Exception e) { Debug.LogError(e); yield break; } string share_addr = "https://www.youtube.com/watch?v=" + broadcast.Id; streamstatusLabel.text = share_addr; Debug.Log($"Get user watch address: {share_addr}"); Debug.Log("======bind LiveBroadcast & LiveStreams Ended======="); #endregion //---for now, create channel ,get rtmp push addr, get user watch addr jobs are done. //---we start to push the streams towards push addr. #region push Stream to rtmp address Debug.Log("======push Stream to rtmp address Started======="); //TODO : #endregion //---switch LiveStream status from Ready to Active #region check LiveStream status if is streaming (ready-->active) Debug.Log("======Switch liveBroadcast Ready to Active Started======="); var liveStreamlist = youtubeService.LiveStreams.List("id,status"); liveStreamlist.Id = broadcast.ContentDetails.BoundStreamId; LiveStreamListResponse returnedList = liveStreamlist.Execute(); List <LiveStream> liveStreams = returnedList.Items as List <LiveStream>; if (liveStreams != null && liveStreams.Count > 0) { LiveStream ls = liveStreams[0]; openURLBtn.interactable = true; if (ls != null) { int errortimes = 0; while (errortimes < 3 && !ls.Status.StreamStatus.Equals("active")) { yield return(new WaitForSeconds(dt)); Debug.Log($"Pending, current stream status: {ls.Status.StreamStatus} {errortimes}"); returnedList = liveStreamlist.Execute(); liveStreams = returnedList.Items as List <LiveStream>; liveStream = liveStreams[0]; errortimes++; } if (errortimes >= 3) { Debug.Log("Streaming Process is Pending. due to there is no streaming push to youtube address."); errortimes = 0; yield break; } } } Debug.Log("======Switch liveBroadcast Ready to Active Ended======="); #endregion //---the broadcast can't transition the status from ready to live directly, //---it must change to testing first and then live. #region transition LiveBroadcasts status (-->testing) Debug.Log("======Test Stream Started======="); var broadCastTestingRequest = youtubeService.LiveBroadcasts.Transition(LiveBroadcastsResource.TransitionRequest.BroadcastStatusEnum.Testing, broadcast.Id, "id,snippet,contentDetails,status"); broadcast = broadCastTestingRequest.Execute(); var liveBroadRequest = youtubeService.LiveBroadcasts.List("id,status"); liveBroadRequest.BroadcastStatus = LiveBroadcastsResource.ListRequest.BroadcastStatusEnum.All; LiveBroadcastListResponse liveBroadcastListResponse = liveBroadRequest.Execute(); List <LiveBroadcast> broadcastReturnedList = liveBroadcastListResponse.Items as List <LiveBroadcast>; if (broadcastReturnedList != null && broadcastReturnedList.Count > 0) { var liveBroadcastReq = broadcastReturnedList[0]; if (liveBroadcastReq != null) { int errortimes = 0; while (errortimes < 3 && !liveBroadcastReq.Status.LifeCycleStatus.Equals("testing")) { yield return(new WaitForSeconds(dt)); Debug.Log("Error publish broadcast - getLifeCycleStatus: " + liveBroadcastReq.Status.LifeCycleStatus); liveBroadcastListResponse = liveBroadRequest.Execute(); broadcastReturnedList = liveBroadcastListResponse.Items as List <LiveBroadcast>; liveBroadcastReq = broadcastReturnedList[0]; errortimes++; } if (errortimes >= 3) { Debug.Log("Streaming Process is Pending. due to there is problem preforming testing."); errortimes = 0; yield break; } } } Debug.Log("======Test Stream Ended======="); #endregion //---transition the status from testing to live #region transition LiveBroadcasts status (testing-->live) var broadCastLiveRequest = youtubeService.LiveBroadcasts.Transition(LiveBroadcastsResource.TransitionRequest.BroadcastStatusEnum.Live, broadcast.Id, "status"); broadcast = broadCastLiveRequest.Execute(); #endregion }