Search code examples
androidyoutube-apiandroid-youtube-apiyoutube-data-api

Inactive stream when going live on youtube through android


I am able to create an event through Youtube api. Event is getting displayed in my Youtube page "events tab" (upcoming category). But when I start streaming it returns the error 403 (stream is inactive).I want to create a new broadcast event everytime I am going live. Any help will be appreciated. Here is my code....

This is in AsyncTask :

YouTube youtube = new YouTube.Builder(transport, jsonFactory,
        credential).setApplicationName(APP_NAME).build();

YouTubeApi.createLiveEvent(youtube, "event description", "event name");    

In method YoutubeApi.createLiveEvent(...) :

public static void createLiveEvent(YouTube youtube, String description,
    String name) {

    try {

        LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
        broadcastSnippet.setTitle(name);
        broadcastSnippet.setScheduledStartTime(new DateTime(new Date()));

        LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
        MonitorStreamInfo monitorStream = new MonitorStreamInfo();
        monitorStream.setEnableMonitorStream(false);
        contentDetails.setMonitorStream(monitorStream);

        // Create LiveBroadcastStatus with privacy status.
        LiveBroadcastStatus status = new LiveBroadcastStatus();
        status.setPrivacyStatus("public");


        LiveBroadcast broadcast = new LiveBroadcast();
        broadcast.setKind("youtube#liveBroadcast");
        broadcast.setSnippet(broadcastSnippet);
        broadcast.setStatus(status);
        broadcast.setContentDetails(contentDetails);

        // Create the insert request
        YouTube.LiveBroadcasts.Insert liveBroadcastInsert = youtube
            .liveBroadcasts().insert("snippet,status,contentDetails",
                broadcast);

        // Request is executed and inserted broadcast is returned
        LiveBroadcast returnedBroadcast = liveBroadcastInsert.execute();

        // Create a snippet with title.
        LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
        streamSnippet.setTitle(name);

        // Create content distribution network with format and ingestion
        // type.
        CdnSettings cdn = new CdnSettings();
        cdn.setFormat("240p");
        cdn.setIngestionType("rtmp");

        LiveStream stream = new LiveStream();
        stream.setKind("youtube#liveStream");
        stream.setSnippet(streamSnippet);
        stream.setCdn(cdn);

        // Create the insert request
        YouTube.LiveStreams.Insert liveStreamInsert = youtube.liveStreams()
            .insert("snippet,cdn", stream);

        // Request is executed and inserted stream is returned
        LiveStream returnedStream = liveStreamInsert.execute();

        // Create the bind request
        YouTube.LiveBroadcasts.Bind liveBroadcastBind = youtube
            .liveBroadcasts().bind(returnedBroadcast.getId(),
                "id,contentDetails");

        // Set stream id to bind
        liveBroadcastBind.setStreamId(returnedStream.getId());

        // Request is executed and bound broadcast is returned
        liveBroadcastBind.execute();

    } catch (GoogleJsonResponseException e) {
        System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage());
        e.printStackTrace();

    } catch (IOException e) {
        System.err.println("IOException: " + e.getMessage());
        e.printStackTrace();
    } catch (Throwable t) {
        System.err.println("Throwable: " + t.getStackTrace());
        t.printStackTrace();
    }
}

Here is my code to start event stream :

public static void startEvent(YouTube youtube, String broadcastId) // broadcast id is same(checked)
        throws IOException {

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Log.e(APP_NAME, "", e);
    }

    YouTube.LiveStreams.List liveBroadcastRequest = youtube
            .liveStreams().list("id,snippet,status");
    // liveBroadcastRequest.setMine(true);
    liveBroadcastRequest.setId(broadcastId);  //  setBroadcastStatus("upcoming");



    // List request is executed and list of broadcasts are returned
    LiveStreamListResponse returnedListResponse = liveBroadcastRequest.execute();
    List<LiveStream> returnedList = returnedListResponse.getItems();


    Transition transitionRequest = youtube.liveBroadcasts().transition(
            "live", broadcastId, "status");
    transitionRequest.execute();
}

The logs of the exception I am receiving:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code": 403,
  "errors": [
    {
      "domain": "youtube.liveBroadcast",
      "message": "Stream is inactive",
      "reason": "errorStreamInactive",
      "extendedHelp": "https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition"
    }
  ],
  "message": "Stream is inactive"
}
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at net.ossrs.yasea.demo.utils.YouTubeApi.startEvent(YouTubeApi.java:236)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:160)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:144)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818

Solution

  • I was facing similar issue few days back...here is what i did...

    Points to remember: a) you may receive a diff RTMP url in API than the youtube events portal.

    b) you may receive 403 error while calling transition on broadcast to status "Live" irrespective of whether you are able to "go live" or not.

    Now issue with error 403(stream is inactive):

    Make sure you are sending frames/data to youtube before calling "transition on broadcast". Now call "Broadcast.transition" on a diff thread with a thread-pause of few seconds(It may take time to send data to youtube).

    eg:

    public static void startEvent(final YouTube youtube, final String broadcastId) throws IOException {

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Log.e(APP_NAME, "", e);
        }
    
        Transition transitionRequest = youtube.liveBroadcasts().transition(
                "live", broadcastId, "status");
        transitionRequest.execute();
    }
    

    I hope this helps....