bitmovin / bitmovin-go

Golang-Client which enables you to seamlessly integrate the new Bitmovin API into your existing projects
MIT License
50 stars 23 forks source link
analytics api-client bitmovin bitmovin-api go golang html5-player video-encoding

bitmovin

New API Client (Recommended)

bitmovin-go is the legacy Bitmovin API client for Golang.

We recommend using the new client, which you can find at bitmovin-api-sdk-go. Using the new client guarantees 100% specification conformity at any given time and access to all features of the API as soon as they are released.


bitmovin-go

Golang-Client which enables you to seamlessly integrate the Bitmovin API into your projects. Using this API client requires an active account. Sign up for a Bitmovin API key.

The full Bitmovin API reference can be found on our website.

Installation

Run go get github.com/bitmovin/bitmovin-go

Also feel free to use your favorite go dependency manager such as glide.

Example

The following example creates a simple transcoding job with a HTTP Input and a S3 Output (create_simple_encoding.go):

package main

import (
    "fmt"
    "time"

    "github.com/bitmovin/bitmovin-go/bitmovin"
    "github.com/bitmovin/bitmovin-go/bitmovintypes"
    "github.com/bitmovin/bitmovin-go/models"
    "github.com/bitmovin/bitmovin-go/services"
)

func main() {
    // Creating Bitmovin object
    bitmovin := bitmovin.NewBitmovin("YOUR API KEY", "https://api.bitmovin.com/v1/", 5)

    // Creating the HTTP Input
    httpIS := services.NewHTTPInputService(bitmovin)
    httpInput := &models.HTTPInput{
        Host: stringToPtr("YOUR HTTP HOST"),
    }
    httpResp, err := httpIS.Create(httpInput)
    errorHandler(httpResp.Status, err)

    s3OS := services.NewS3OutputService(bitmovin)
    s3Output := &models.S3Output{
        AccessKey:   stringToPtr("YOUR_ACCESS_KEY"),
        SecretKey:   stringToPtr("YOUR_SECRET_KEY"),
        BucketName:  stringToPtr("YOUR_BUCKET_NAME"),
        CloudRegion: bitmovintypes.AWSCloudRegionEUWest1,
    }
    s3OutputResp, err := s3OS.Create(s3Output)
    errorHandler(s3OutputResp.Status, err)

    encodingS := services.NewEncodingService(bitmovin)
    encoding := &models.Encoding{
        Name:        stringToPtr("example encoding"),
        CloudRegion: bitmovintypes.CloudRegionGoogleEuropeWest1,
    }
    encodingResp, err := encodingS.Create(encoding)
    errorHandler(encodingResp.Status, err)

    h264S := services.NewH264CodecConfigurationService(bitmovin)
    video1080pConfig := &models.H264CodecConfiguration{
        Name:      stringToPtr("example_video_codec_configuration_1080p"),
        Bitrate:   intToPtr(4800000),
        FrameRate: floatToPtr(25.0),
        Width:     intToPtr(1920),
        Height:    intToPtr(1080),
        Profile:   bitmovintypes.H264ProfileHigh,
    }
    video720Config := &models.H264CodecConfiguration{
        Name:      stringToPtr("example_video_codec_configuration_720p"),
        Bitrate:   intToPtr(2400000),
        FrameRate: floatToPtr(25.0),
        Width:     intToPtr(1280),
        Height:    intToPtr(720),
        Profile:   bitmovintypes.H264ProfileHigh,
    }
    video1080pResp, err := h264S.Create(video1080pConfig)
    errorHandler(video1080pResp.Status, err)
    video720Resp, err := h264S.Create(video720Config)
    errorHandler(video720Resp.Status, err)

    aacS := services.NewAACCodecConfigurationService(bitmovin)
    aacConfig := &models.AACCodecConfiguration{
        Name:         stringToPtr("example_audio_codec_configuration"),
        Bitrate:      intToPtr(128000),
        SamplingRate: floatToPtr(48000.0),
    }
    aacResp, err := aacS.Create(aacConfig)
    errorHandler(aacResp.Status, err)

    videoInputStream := models.InputStream{
        InputID:       httpResp.Data.Result.ID,
        InputPath:     stringToPtr("YOUR INPUT FILE PATH AND LOCATION"),
        SelectionMode: bitmovintypes.SelectionModeAuto,
    }
    audioInputStream := models.InputStream{
        InputID:       httpResp.Data.Result.ID,
        InputPath:     stringToPtr("YOUR INPUT FILE PATH AND LOCATION"),
        SelectionMode: bitmovintypes.SelectionModeAuto,
    }

    vis := []models.InputStream{videoInputStream}
    videoStream1080p := &models.Stream{
        CodecConfigurationID: video1080pResp.Data.Result.ID,
        InputStreams:         vis,
    }
    videoStream720p := &models.Stream{
        CodecConfigurationID: video720Resp.Data.Result.ID,
        InputStreams:         vis,
    }

    videoStream1080pResp, err := encodingS.AddStream(*encodingResp.Data.Result.ID, videoStream1080p)
    errorHandler(videoStream1080pResp.Status, err)
    videoStream720pResp, err := encodingS.AddStream(*encodingResp.Data.Result.ID, videoStream720p)
    errorHandler(videoStream720pResp.Status, err)

    ais := []models.InputStream{audioInputStream}
    audioStream := &models.Stream{
        CodecConfigurationID: aacResp.Data.Result.ID,
        InputStreams:         ais,
    }
    aacStreamResp, err := encodingS.AddStream(*encodingResp.Data.Result.ID, audioStream)
    errorHandler(aacStreamResp.Status, err)

    aclEntry := models.ACLItem{
        Permission: bitmovintypes.ACLPermissionPublicRead,
    }
    acl := []models.ACLItem{aclEntry}

    videoMuxingStream1080p := models.StreamItem{
        StreamID: videoStream1080pResp.Data.Result.ID,
    }
    videoMuxingStream720p := models.StreamItem{
        StreamID: videoStream720pResp.Data.Result.ID,
    }
    audioMuxingStream := models.StreamItem{
        StreamID: aacStreamResp.Data.Result.ID,
    }

    videoMuxing1080pOutput := models.Output{
        OutputID:   s3OutputResp.Data.Result.ID,
        OutputPath: stringToPtr("golang_test/video/1080p"),
        ACL:        acl,
    }
    videoMuxing720pOutput := models.Output{
        OutputID:   s3OutputResp.Data.Result.ID,
        OutputPath: stringToPtr("golang_test/video/720p"),
        ACL:        acl,
    }
    audioMuxingOutput := models.Output{
        OutputID:   s3OutputResp.Data.Result.ID,
        OutputPath: stringToPtr("golang_test/audio"),
        ACL:        acl,
    }

    videoMuxing1080p := &models.FMP4Muxing{
        SegmentLength:   floatToPtr(4.0),
        SegmentNaming:   stringToPtr("seg_%number%.m4s"),
        InitSegmentName: stringToPtr("init.mp4"),
        Streams:         []models.StreamItem{videoMuxingStream1080p},
        Outputs:         []models.Output{videoMuxing1080pOutput},
    }
    videoMuxing1080pResp, err := encodingS.AddFMP4Muxing(*encodingResp.Data.Result.ID, videoMuxing1080p)
    errorHandler(videoMuxing1080pResp.Status, err)

    videoMuxing720p := &models.FMP4Muxing{
        SegmentLength:   floatToPtr(4.0),
        SegmentNaming:   stringToPtr("seg_%number%.m4s"),
        InitSegmentName: stringToPtr("init.mp4"),
        Streams:         []models.StreamItem{videoMuxingStream720p},
        Outputs:         []models.Output{videoMuxing720pOutput},
    }
    videoMuxing720pResp, err := encodingS.AddFMP4Muxing(*encodingResp.Data.Result.ID, videoMuxing720p)
    errorHandler(videoMuxing720pResp.Status, err)

    audioMuxing := &models.FMP4Muxing{
        SegmentLength:   floatToPtr(4.0),
        SegmentNaming:   stringToPtr("seg_%number%.m4s"),
        InitSegmentName: stringToPtr("init.mp4"),
        Streams:         []models.StreamItem{audioMuxingStream},
        Outputs:         []models.Output{audioMuxingOutput},
    }
    audioMuxingResp, err := encodingS.AddFMP4Muxing(*encodingResp.Data.Result.ID, audioMuxing)
    errorHandler(audioMuxingResp.Status, err)

    startResp, err := encodingS.Start(*encodingResp.Data.Result.ID)
    errorHandler(startResp.Status, err)

    var status string
    status = ""
    for status != "FINISHED" {
        time.Sleep(10 * time.Second)
        statusResp, err := encodingS.RetrieveStatus(*encodingResp.Data.Result.ID)
        if err != nil {
            fmt.Println("error in Encoding Status")
            fmt.Println(err)
            return
        }
        // Polling and Printing out the response
        fmt.Printf("%+v\n", statusResp)
        status = *statusResp.Data.Result.Status
        if status == "ERROR" {
            fmt.Println("error in Encoding Status")
            fmt.Printf("%+v\n", statusResp)
            return
        }
    }

    manifestOutput := models.Output{
        OutputID:   s3OutputResp.Data.Result.ID,
        OutputPath: stringToPtr("golang_test/manifest"),
        ACL:        acl,
    }
    dashManifest := &models.DashManifest{
        ManifestName: stringToPtr("your_manifest_name.mpd"),
        Outputs:      []models.Output{manifestOutput},
    }
    dashService := services.NewDashManifestService(bitmovin)
    dashManifestResp, err := dashService.Create(dashManifest)
    errorHandler(dashManifestResp.Status, err)

    period := &models.Period{}
    periodResp, err := dashService.AddPeriod(*dashManifestResp.Data.Result.ID, period)
    errorHandler(periodResp.Status, err)

    vas := &models.VideoAdaptationSet{}
    vasResp, err := dashService.AddVideoAdaptationSet(*dashManifestResp.Data.Result.ID, *periodResp.Data.Result.ID, vas)
    errorHandler(vasResp.Status, err)

    aas := &models.AudioAdaptationSet{
        Language: stringToPtr("en"),
    }
    aasResp, err := dashService.AddAudioAdaptationSet(*dashManifestResp.Data.Result.ID, *periodResp.Data.Result.ID, aas)
    errorHandler(aasResp.Status, err)

    fmp4Rep1080 := &models.FMP4Representation{
        Type:        bitmovintypes.FMP4RepresentationTypeTemplate,
        MuxingID:    videoMuxing1080pResp.Data.Result.ID,
        EncodingID:  encodingResp.Data.Result.ID,
        SegmentPath: stringToPtr("../video/1080p"),
    }
    fmp4Rep1080Resp, err := dashService.AddFMP4Representation(*dashManifestResp.Data.Result.ID, *periodResp.Data.Result.ID, *vasResp.Data.Result.ID, fmp4Rep1080)
    errorHandler(fmp4Rep1080Resp.Status, err)

    fmp4Rep720 := &models.FMP4Representation{
        Type:        bitmovintypes.FMP4RepresentationTypeTemplate,
        MuxingID:    videoMuxing720pResp.Data.Result.ID,
        EncodingID:  encodingResp.Data.Result.ID,
        SegmentPath: stringToPtr("../video/720p"),
    }
    fmp4Rep720Resp, err := dashService.AddFMP4Representation(*dashManifestResp.Data.Result.ID, *periodResp.Data.Result.ID, *vasResp.Data.Result.ID, fmp4Rep720)
    errorHandler(fmp4Rep720Resp.Status, err)

    fmp4RepAudio := &models.FMP4Representation{
        Type:        bitmovintypes.FMP4RepresentationTypeTemplate,
        MuxingID:    audioMuxingResp.Data.Result.ID,
        EncodingID:  encodingResp.Data.Result.ID,
        SegmentPath: stringToPtr("../audio"),
    }
    fmp4RepAudioResp, err := dashService.AddFMP4Representation(*dashManifestResp.Data.Result.ID, *periodResp.Data.Result.ID, *aasResp.Data.Result.ID, fmp4RepAudio)
    errorHandler(fmp4RepAudioResp.Status, err)

    startResp, err = dashService.Start(*dashManifestResp.Data.Result.ID)
    errorHandler(startResp.Status, err)

    status = ""
    for status != "FINISHED" {
        time.Sleep(5 * time.Second)
        statusResp, err := dashService.RetrieveStatus(*dashManifestResp.Data.Result.ID)
        if err != nil {
            fmt.Println("error in Manifest Status")
            fmt.Println(err)
            return
        }
        // Polling and Printing out the response
        fmt.Printf("%+v\n", statusResp)
        status = *statusResp.Data.Result.Status
        if status == "ERROR" {
            fmt.Println("error in Manifest Status")
            fmt.Printf("%+v\n", statusResp)
            return
        }
    }

    // Delete Encoding
    deleteResp, err := encodingS.Delete(*encodingResp.Data.Result.ID)
    errorHandler(deleteResp.Status, err)
}

func errorHandler(responseStatus bitmovintypes.ResponseStatus, err error) {
    if err != nil {
        fmt.Println("go error")
        fmt.Println(err)
    } else if responseStatus == "ERROR" {
        fmt.Println("api error")
    }
}

func stringToPtr(s string) *string {
    return &s
}

func intToPtr(i int64) *int64 {
    return &i
}

func boolToPtr(b bool) *bool {
    return &b
}

func floatToPtr(f float64) *float64 {
    return &f
}

For more examples go to our example page.

Contributing

bitmovin-go is licensed under the MIT license. If you want to contribute feel free to send Pull-Requests.