youtube: functionality for set up of youtube broadcast and accompanying stream

Issue #107 resolved
Saxon Milton created an issue

This is a sub issue of issue #105

After an authorisation process (issue #106) from which a usable youtube “client” is built. We will need to be able to configure broadcasts and streams, and then bind, allowing for RTMP streaming from one of cameras to the configured youtube “event”. In lack of a go based YouTube API streaming setup example, it’s proposed that insight be found from this python based example. The equivalent functionality can be discovered in the go YouTube API godoc.

Comments (5)

  1. kortschak
  2. kortschak

    When you are ready with the auth code, this should plug in.

    package broadcast
    
    import (
        "log"
        "time"
    
        "google.golang.org/api/googleapi"
        "google.golang.org/api/youtube/v3"
    )
    
    // breadcastStream corresponds to the logic in https://github.com/youtube/api-samples/blob/07263305b59a7c3275bc7e925f9ce6cabf774022/python/create_broadcast.py#L135-L138
    func broadcastStream(svc *youtube.Service, broadcast, stream, privacy, format, typ string, start, end time.Time, opts ...googleapi.CallOption) (googleapi.ServerResponse, error) {
        bID, resp, err := insertBroadcast(svc, broadcast, privacy, start, end, opts...)
        if err != nil {
            return resp, err
        }
    
        // stream_id = insert_stream(youtube, args)
        sID, resp, err := insertStream(svc, stream, format, typ, opts...)
        if err != nil {
            return resp, err
        }
    
        // bind_broadcast(youtube, broadcast_id, stream_id)
        return bindBroadcast(svc, bID, sID, opts...)
    }
    
    // insertBroadcast corresponds to https://github.com/youtube/api-samples/blob/07263305b59a7c3275bc7e925f9ce6cabf774022/python/create_broadcast.py#L63-L84
    func insertBroadcast(svc *youtube.Service, broadcast, privacy string, start, end time.Time, opts ...googleapi.CallOption) (id string, servResp googleapi.ServerResponse, err error) {
        // broadcast_id = insert_broadcast(youtube, args)
        b := youtube.NewLiveBroadcastsService(svc)
        resp, err := b.Insert([]string{"snippet", "status"}, &youtube.LiveBroadcast{
            Snippet: &youtube.LiveBroadcastSnippet{
                Title:              broadcast,
                ScheduledStartTime: start.Format(time.RFC3339),
                ScheduledEndTime:   end.Format(time.RFC3339),
            },
            Status: &youtube.LiveBroadcastStatus{
                PrivacyStatus: privacy,
            },
        }).Do(opts...)
        if err != nil {
            return "", resp.ServerResponse, err
        }
        log.Printf("Broadcast %q with title %q was published at %v.",
            resp.Id, resp.Snippet.Title, resp.Snippet.PublishedAt)
        return resp.Id, resp.ServerResponse, nil
    }
    
    // insertStream corresponds to https://github.com/youtube/api-samples/blob/07263305b59a7c3275bc7e925f9ce6cabf774022/python/create_broadcast.py#L86-L106
    func insertStream(svc *youtube.Service, stream, format, typ string, opts ...googleapi.CallOption) (id string, servResp googleapi.ServerResponse, err error) {
        s := youtube.NewLiveStreamsService(svc)
        resp, err := s.Insert([]string{"snippet", "cdn"}, &youtube.LiveStream{
            Snippet: &youtube.LiveStreamSnippet{
                Title: stream,
            },
            Cdn: &youtube.CdnSettings{
                Format:        format,
                IngestionType: typ,
            },
        }).Do(opts...)
        if err != nil {
            return "", resp.ServerResponse, err
        }
        log.Printf("Stream %q with title %q was inserted.",
            resp.Id, resp.Snippet.Title)
        return resp.Id, resp.ServerResponse, nil
    }
    
    // bindBroadcast corresponds to https://github.com/youtube/api-samples/blob/07263305b59a7c3275bc7e925f9ce6cabf774022/python/create_broadcast.py#L108-L119
    func bindBroadcast(svc *youtube.Service, bID, sID string, opts ...googleapi.CallOption) (googleapi.ServerResponse, error) {
        resp, err := svc.LiveBroadcasts.Bind(bID, []string{"id", "contentDetails"}).StreamId(sID).Do(opts...)
        if err != nil {
            return resp.ServerResponse, err
        }
        log.Printf("Broadcast %q was bound to stream %q.",
            resp.Id, resp.ContentDetails.BoundStreamId)
        return resp.ServerResponse, nil
    }
    
  3. kortschak

    Stream and broadcast removal are obvious extensions from this code. The documentation is terrible for the Go package, so I found that it was necessary to read the python docs which help, though there are structural differences between the two languages that need thought (a good example of this is the approach in svc.LiveBroadcasts.Bind(bID, []string{"id", "contentDetails"}).StreamId(sID).Do(opts...) compared to the python code which is youtube.liveBroadcasts().bind(part="id,contentDetails", id=broadcast_id, streamId=stream_id).execute().

    The python docs are here with the broadcasts here and livestreams here.

  4. Log in to comment