YouTube Live API Stream Status and Quality Callback

3.2k Views Asked by At

In the "Live Control Room" of a YouTube Live broadcast, I can see a "Stream Status" view which shows me details of the video being sent to YouTube's RTMP endpoint.Stream Status

I hit the liveStreams endpoint to get the "status" of the stream, but that only returns active, meaning that the video stream is being successfully sent to YouTube's RTMP endpoint, but no information about video data or quality.

Is this information exposed somewhere in the API? Can I also see additional details about the video, such as the bitrate, fps, etc. being sent to YouTube so I can verify my encoder is working correctly? Or does that check need to be done on the client-side and check the video right after it leaves the encoder before hitting the RTMP endpoint. I'm writing an iOS application, so using the "Live Control Room" on the web isn't a viable solution for me.

Here's what I'm doing on the broadcasting side to check the liveStream status:

- (void)checkStreamStatus {
    [self getRequestWithURL:[NSString stringWithFormat:@"https://www.googleapis.com/youtube/v3/liveStreams?part=id,snippet,cdn,status&id=%@", self.liveStreamId] andBlock:^(NSDictionary *responseDict) {
        NSLog(@"response: %@", responseDict);

        // if stream is active, youtube is receiving data from our encoder
        // ready to transition to live
        NSArray *items = [responseDict objectForKey:@"items"];
        NSDictionary *itemsDict = [items firstObject];
        NSDictionary *statusDict = [itemsDict objectForKey:@"status"];
        if ([[statusDict objectForKey:@"streamStatus"] isEqualToString:@"active"]) {
            NSLog(@"stream ready to go live!");
            if (!userIsLive) {
                [self goLive]; // transition the broadcastStatus from "testing" to "live"
            }
        } else {
            NSLog(@"keep refreshing, broadcast object not ready on youtube's end");
        }
    }];
}

getRequestWithURL is just a generic method I created to do GET requests:

- (void)getRequestWithURL:(NSString *)urlStr andBlock:(void (^)(NSDictionary *responseDict))completion {

    NSURL *url = [NSURL URLWithString:urlStr];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];

    [request addValue:[NSString stringWithFormat:@"Bearer %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"accessToken"]] forHTTPHeaderField:@"Authorization"];

    [request setHTTPMethod:@"GET"];

    // Set the content type
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        [self parseJSONwithData:data andBlock:completion];

    }];
}

- (void)parseJSONwithData:(NSData *)data andBlock:(void (^)(NSDictionary * responseDict))completion {
    NSError *error = nil;
    NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data
                                                                 options:kNilOptions
                                                                   error:&error];
    if (error) {
        NSLog(@"error: %@", [error localizedDescription]);
    }
    completion(responseDict);
}

Here's what I'm doing on the consumer side to check the video quality:

I am using the YTPlayerView library from Google.

- (void)notifyDelegateOfYouTubeCallbackUrl: (NSURL *) url {
  NSString *action = url.host;

  // We know the query can only be of the format http://ytplayer?data=SOMEVALUE,
  // so we parse out the value.
  NSString *query = url.query;
  NSString *data;
  if (query) {
    data = [query componentsSeparatedByString:@"="][4]; // data here is auto, meaning auto quality
  }
  ...
  if ([action isEqual:kYTPlayerCallbackOnPlaybackQualityChange]) {
    if ([self.delegate respondsToSelector:@selector(playerView:didChangeToQuality:)]) {
    YTPlaybackQuality quality = [YTPlayerView playbackQualityForString:data];
    [self.delegate playerView:self didChangeToQuality:quality];
  }
  ...
}

But the quality "auto" doesn't seem to be a supported quality constant in this library:

// Constants representing playback quality.
NSString static *const kYTPlaybackQualitySmallQuality = @"small";
NSString static *const kYTPlaybackQualityMediumQuality = @"medium";
NSString static *const kYTPlaybackQualityLargeQuality = @"large";
NSString static *const kYTPlaybackQualityHD720Quality = @"hd720";
NSString static *const kYTPlaybackQualityHD1080Quality = @"hd1080";
NSString static *const kYTPlaybackQualityHighResQuality = @"highres";
NSString static *const kYTPlaybackQualityUnknownQuality = @"unknown";

...
@implementation YTPlayerView
...

/**
 * Convert a quality value from NSString to the typed enum value.
 *
 * @param qualityString A string representing playback quality. Ex: "small", "medium", "hd1080".
 * @return An enum value representing the playback quality.
 */
+ (YTPlaybackQuality)playbackQualityForString:(NSString *)qualityString {
  YTPlaybackQuality quality = kYTPlaybackQualityUnknown;

  if ([qualityString isEqualToString:kYTPlaybackQualitySmallQuality]) {
    quality = kYTPlaybackQualitySmall;
  } else if ([qualityString isEqualToString:kYTPlaybackQualityMediumQuality]) {
    quality = kYTPlaybackQualityMedium;
  } else if ([qualityString isEqualToString:kYTPlaybackQualityLargeQuality]) {
    quality = kYTPlaybackQualityLarge;
  } else if ([qualityString isEqualToString:kYTPlaybackQualityHD720Quality]) {
    quality = kYTPlaybackQualityHD720;
  } else if ([qualityString isEqualToString:kYTPlaybackQualityHD1080Quality]) {
    quality = kYTPlaybackQualityHD1080;
  } else if ([qualityString isEqualToString:kYTPlaybackQualityHighResQuality]) {
    quality = kYTPlaybackQualityHighRes;
  }

  return quality;
}

I created a issue for this on the project's GitHub page.

2

There are 2 best solutions below

0
On BEST ANSWER

I received a reply from Ibrahim Ulukaya about this issue:

We are hoping to have more information to that call, but basically active indicates the good streaming, and your streaming info is https://developers.google.com/youtube/v3/live/docs/liveStreams#cdn.format where you set, and can see the format.

So the answer for the time being is no, this information is not available from the YouTube Livestreaming API for the time being. I will updated this answer if/when the API is updated.

0
On

It seems Youtube Live streaming API has been updated to show Live stream health status with this property: status.healthStatus.status

See their latest API for more info.