本文提供了直接调用导播台openAPI的Demo,具体逻辑请根据实际情况自行编写。

导播台生命流程

导播台整个生命流程顺序如下 :
  1. 创建导播台
  2. 设置导播台
  3. 添加视频资源
  4. 添加布局
  5. (可选)添加组件

    组件包括ET字幕、图片、文字等,可以不创建,请根据实际情况选择是否使用。

  6. 启动导播台
  7. 设置播放场景
  8. 停止导播台
  9. 删除导播台

示例代码

说明 了解API的详细信息,请参见API概述

语言:Go。

  • 创建导播台
    package caster
    
    import (
        "github.com/aliyun/alibaba-cloud-sdk-go/services/live"
        uuid "github.com/satori/go.uuid"
        "testing"
    )
    
    // 创建导播台
    func CreateCaster(t *testing.T) {
        liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
        if err != nil {
            t.Fatal(err)
        }
    
        // 创建导播台请求参数
        createCasterRequest := live.CreateCreateCasterRequest()
        createCasterRequest.ClientToken = uuid.NewV1().String()
        createCasterRequest.CasterName = "导播台测试" // 不生效的话,请通过接口【设置导播台】来设置
        createCasterRequest.ChargeType = "PostPaid"
        createCasterRequest.NormType = "1"
        _, err = liveClient.CreateCaster(createCasterRequest)
        if err != nil {
            t.Fatal(err)
        }
    }

    关于CreateCaster接口的请求参数等更多信息,请参见创建导播台

  • 设置导播台
    package caster
    
    import (
        "github.com/aliyun/alibaba-cloud-sdk-go/services/live"
        "testing"
    )
    
    // 设置导播台
    func SetCasterConfig(t *testing.T) {
        liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
        if err != nil {
            t.Fatal(err)
        }
    
        // 设置导播台配置参数
        createSetCasterConfig := live.CreateSetCasterConfigRequest()
        createSetCasterConfig.CasterId = "xxxxxx"
        createSetCasterConfig.CasterName = "导播台测试"
        createSetCasterConfig.ChannelEnable = "1"
        createSetCasterConfig.Delay = "0"
        createSetCasterConfig.DomainName = "xxxxxxxx"
        createSetCasterConfig.ProgramEffect = "1"
        createSetCasterConfig.ProgramName = "test loop play"
        // 转码设置(横竖屏模式及清晰度设置)
        // 参考如下文档:
        // https://help.aliyun.com/document_detail/60271.html
        // 其中:CasterTemplate取值范围如下
        // lp_ld:流畅、lp_sd:标清、lp_hd:高清、lp_ud:超清。
        // lp_ld_v:竖屏流畅、lp_sd_v:竖屏标清、lp_hd_v:竖屏高清、lp_ud_v:竖屏超清。
        createSetCasterConfig.TranscodeConfig = `{"CasterTemplate": "lp_ld"}`
        // 录制
        // json字段含义请参考:https://help.aliyun.com/document_detail/35416.htm?spm=a2c4g.11186623.2.25.5e7b102dodnYPU#doc-api-live-AddLiveAppRecordConfig
        createSetCasterConfig.RecordConfig = fmt.Sprintf(`{ "endpoint": "oss-cn-shanghai.aliyuncs.com", "ossBucket": "test-record", "videoFormat": [{"format": "flv", "interval": 900, "prefix":"record/{AppName}/{StreamName}/{StartTime}_{EndTime}" }]}`)
        _, err = liveClient.SetCasterConfig(createSetCasterConfig)
        if err != nil {
            t.Fatal(err)
        }
    }

    关于SetCasterConfig接口的更多信息,请参见配置导播台

  • 添加资源及绑定到通道
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    
    // 添加资源
    func AddCasterVideoResource(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 创建导播台视频资源
    	addCasterVideoResourceRequest := live.CreateAddCasterVideoResourceRequest()
    	addCasterVideoResourceRequest.CasterId = "xxxx"
    	addCasterVideoResourceRequest.ResourceName = "测试使用视频资源"
    	addCasterVideoResourceRequest.LiveStreamUrl = "xxxxxxxxxxxx"
    	addCasterVideoResourceRequest.PtsCallbackInterval = "1000"
    	addCasterVideoResourceResp, err := liveClient.AddCasterVideoResource(addCasterVideoResourceRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    	resourceID := addCasterVideoResourceResp.ResourceId
    
    	// 视频资源与通道一一绑定
    	setCasterChannelRequest := live.CreateSetCasterChannelRequest()
    	setCasterChannelRequest.CasterId = "xxx"
    	setCasterChannelRequest.PlayStatus = "1"
    	setCasterChannelRequest.ChannelId = "RV01"
    	setCasterChannelRequest.ResourceId = resourceID
    	_, err = liveClient.SetCasterChannel(setCasterChannelRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于AddCasterVideoResource接口的更多信息,请参见添加导播台视频资源

  • 添加布局
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    
    // 添加布局
    func AddCasterLayout(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 创建布局
    	addCasterLayoutRequest := live.CreateAddCasterLayoutRequest()
    	addCasterLayoutRequest.CasterId = "xxx"
    	addCasterLayoutRequest.BlendList = &[]string{"RV01"} // 对应于视频的位置
    	addCasterLayoutRequest.MixList = &[]string{"RV01"} // 对应于视频的位置
    	addCasterLayoutRequest.AudioLayer = &[]live.AddCasterLayoutAudioLayer{
    		{
    			VolumeRate:         "1",
    			ValidChannel:       "all",
    			FixedDelayDuration: "0",
    		},
    	}
    	addCasterLayoutRequest.VideoLayer = &[]live.AddCasterLayoutVideoLayer{
    		{
    			FillMode:           "fit",
    			HeightNormalized:   "1",
    			WidthNormalized:    "1",
    			PositionRefer:      "topLeft",
    			PositionNormalized: &[]string{"0", "0"},
    			FixedDelayDuration: "0",
    		},
    	}
    	_, err = liveClient.AddCasterLayout(addCasterLayoutRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于AddCasterLayout接口的更多信息,请参见添加导播台布局

  • 添加ET字幕组件并应用到场景
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    
    // 添加ET字幕组件并应用到场景
    func AddETComponent(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    	// 此方法前提: 导播台已经存在,且添加的视频资源是直播流,且locationID是RV01
    	// 注:ET字幕必须是直播流才有效
    	casterID := "xxxxx"
    	// 创建组件
    	r := live.CreateAddCasterComponentRequest()
    	r.CasterId = casterID
    	r.ComponentType = "caption"
    	r.ComponentName = "ET字幕测试使用"
    	r.Effect = "none"
    	r.LocationId = "RC01"
    	r.ComponentLayer = `{"HeightNormalized":"1","WidthNormalized":"1","PositionRefer":"topLeft","PositionNormalized":["0.05", "0.7"]}`
    	// 字幕具体字段请参考:https://help.aliyun.com/document_detail/63160.html?spm=a2c4g.11186623.6.879.42aa25ee965ctW 文档内的【CaptionLayerContent】字段说明
    	// 其中新增以下字段,目前官网文档尚未更新,请注意
    	// BoxWidthNormalized:文字背景宽度归一化值,该归一化值是基于文字的size来计算的,即boxWidth/font_size, 如果系统归一化反计算出来的值超过16,取16. 默认0。
    	// BoxColor:文字背景色彩,取值格式为 0xRGBA,比如: 取值"0xff0000ff" 表示红色, 不透明 默认"" 表示无效。
    	// ShadowxWidthNormalized:文字阴影x坐标归一化值,该归一化值是基于文字的size来计算的,即shadowxWidthNormalized/font_size, 如果系统归一化反计算出来的值超过16,取16. 默认0。
    	// ShadowyWidthNormalized:文字阴影y坐标归一化值,该归一化值是基于文字的size来计算的,即shadowyWidthNormalized/font_size, 如果系统归一化反计算出来的值超过16,取16. 默认0。
    	// ShadowColor:文字阴影色彩,取值格式为 0xRGBA,比如: 取值"0xff0000ff" 表示红色, 不透明 默认"" 表示无效。
    	r.CaptionLayerContent = `{
    		"SizeNormalized": 0.05,
    		"Color": "0xFFFFFF",
    		"LocationId": "RV01",
    		"BorderColor": "0x696969",
    		"BorderWidthNormalized": 0.1,
    		"BoxColor": "0xffffff",
    		"BoxWidthNormalized": 0.7,
    		"ShadowColor": "0x3c3c3c",
    		"ShadowxWidthNormalized": 0.4,
    		"ShadowyWidthNormalized": 0.4,
    		"SourceLan": "cn",
    		"TargetLan": "en",
    		"PtsOffset": -1000,
    		"SourceLanPerLineWordCount": 28,
    		"TargetLanPerLineWordCount": 60,
    		"ShowSourceLan": true,
    		"ShowTargetLan": true,
    		"Truncation": false,
    		"AppearDuration": 20000,
    		"AppearMode": "Movie"
    	}`
    	addCasterComponentResp, err := liveClient.AddCasterComponent(r)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 应用组件到指定的场景下
    	setCasterSceneConfigRequest := live.CreateUpdateCasterSceneConfigRequest()
    	setCasterSceneConfigRequest.LayoutId = "xxxxx"
    	setCasterSceneConfigRequest.CasterId = casterID
    	setCasterSceneConfigRequest.SceneId = "xxxx"
    	setCasterSceneConfigRequest.ComponentId = &[]string{addCasterComponentResp.ComponentId}
    	_, err = liveClient.UpdateCasterSceneConfig(setCasterSceneConfigRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于AddCasterComponent接口的更多信息,请参见添加导播台组件

    关于SetCasterSceneConfig接口的更多信息,请参见设置场景配置

  • 启动导播台、设置播放场景
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    	"time"
    )
    
    // 启动导播台、设置播放场景
    func StartCaster(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 启动导播台
    	startCasterRequest := live.CreateStartCasterRequest()
    	startCasterRequest.CasterId = "xxx"
    	startCasterResp, err := liveClient.StartCaster(startCasterRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 因为资源加载需要时间,如果立马启动,则可能资源尚未加载成功,所以需要暂停一下
    	time.Sleep(time.Second)
    
    	// 设置播放场景
    	// PVW (可选设置)
    	setCasterSceneConfigRequest := live.CreateSetCasterSceneConfigRequest()
    	setCasterSceneConfigRequest.LayoutId = "xxx"
    	setCasterSceneConfigRequest.CasterId = "xxx"
    	setCasterSceneConfigRequest.SceneId = startCasterResp.PvwSceneInfos.SceneInfo[0].SceneId
    	_, err = liveClient.SetCasterSceneConfig(setCasterSceneConfigRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    	// PGM (必选设置)
    	setCasterSceneConfigRequest.SceneId = startCasterResp.PgmSceneInfos.SceneInfo[0].SceneId
    	_, err = liveClient.SetCasterSceneConfig(setCasterSceneConfigRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于StartCaster接口的更多信息,请参见启动导播台

    关于SetCasterSceneConfig接口的更多信息,请参见设置场景配置

  • 切换布局
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    // 切换布局
    func ChangeLayout(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    	casterID := "xxxxxx"
    
    	// 更改场景使用的布局ID
    	setCasterSceneConfigRequest := live.CreateUpdateCasterSceneConfigRequest()
    	setCasterSceneConfigRequest.LayoutId = "xxxxxxxxxxxx"
    	setCasterSceneConfigRequest.CasterId = casterID
    	setCasterSceneConfigRequest.SceneId = "xxxxxxxxxxxxxx"
    	_, err = liveClient.UpdateCasterSceneConfig(setCasterSceneConfigRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于SetCasterSceneConfig接口的更多信息,请参见设置场景配置

  • 停止导播台
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    // 停止导播台
    func StopCaster(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("", "", "")
    	if err != nil {
    		t.Fatal(err)
    	}
    	// 停止导播台
    	stopCasterRequest := live.CreateStopCasterRequest()
    	stopCasterRequest.CasterId = "xxxx"
    	_, err = liveClient.StopCaster(stopCasterRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于StopCaster接口的更多信息,请参见停止导播台

  • 删除导播台
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"testing"
    )
    // 停止并删除导播台
    func DeleteCaster(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("", "", "")
    	if err != nil {
    		t.Fatal(err)
    	}
    	// 删除导播台
    	deleteCasterRequest := live.CreateDeleteCasterRequest()
    	deleteCasterRequest.CasterId = "xxxxxxx"
    	_, err = liveClient.DeleteCaster(deleteCasterRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }

    关于DeleteCaster接口的更多信息,请参见删除导播台

  • 启动并创建一个节目单
    package caster
    
    import (
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/live"
    	"github.com/aliyun/alibaba-cloud-sdk-go/services/vod"
    	uuid "github.com/satori/go.uuid"
    	"strconv"
    	"testing"
    	"time"
    )
    
    // 使用最简单的方式,创建并启动一个节目单
    func CreateProgramAndStartup(t *testing.T) {
    	liveClient, err := live.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    	vodClient, err := vod.NewClientWithAccessKey("xxx", "xxx", "xxx")
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 创建导播台
    	createCasterRequest := live.CreateCreateCasterRequest()
    	createCasterRequest.ClientToken = uuid.NewV1().String()
    	createCasterRequest.CasterName = "导播台节目单测试"
    	createCasterRequest.ChargeType = "PostPaid"
    	createCasterRequest.NormType = "0"
    	createCasterResp, err := liveClient.CreateCaster(createCasterRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    	casterID := createCasterResp.CasterId
    
    	// 设置导播台配置
    	createSetCasterConfig := live.CreateSetCasterConfigRequest()
    	createSetCasterConfig.CasterId = casterID
    	createSetCasterConfig.CasterName = "导播台节目单测试"
    	createSetCasterConfig.ChannelEnable = "0"
    	createSetCasterConfig.Delay = "0"
    	createSetCasterConfig.DomainName = "xxxxxxxxxxx"
    	createSetCasterConfig.ProgramEffect = "1"
    	createSetCasterConfig.ProgramName = "导播台节目名称"
    	createSetCasterConfig.TranscodeConfig = `{"LiveTemplate":["lld"], "CasterTemplate": "lp_ld"}`
    	_, err = liveClient.SetCasterConfig(createSetCasterConfig)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 创建导播台视频资源
    	materialVideoID := "xxxxxxxx"
    	locationID := "RV01"
    	addCasterVideoResourceRequest := live.CreateAddCasterVideoResourceRequest()
    	addCasterVideoResourceRequest.CasterId = casterID
    	addCasterVideoResourceRequest.ResourceName = "测试使用视频资源"
    	addCasterVideoResourceRequest.PtsCallbackInterval = "1000"
    	addCasterVideoResourceRequest.LocationId = locationID
    	addCasterVideoResourceRequest.MaterialId = materialVideoID
    
    	addCasterVideoResourceResp, err := liveClient.AddCasterVideoResource(addCasterVideoResourceRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    	resourceID := addCasterVideoResourceResp.ResourceId
    
    	// 创建节目单
    	baseTimeNow := time.Now().UTC().Add(time.Minute)
    	req := vod.CreateGetMezzanineInfoRequest()
    	req.VideoId = materialVideoID
    	mezzanineInfoResp, err := vodClient.GetMezzanineInfo(req)
    	duration, _ := strconv.ParseFloat(mezzanineInfoResp.Mezzanine.Duration, 64)
    	startTime := baseTimeNow.Format("2006-01-02T15:04:05Z")
    	baseTimeNow = baseTimeNow.Add(time.Duration(duration) * time.Second)
    	endTime := baseTimeNow.Format("2006-01-02T15:04:05Z")
    	episode := make([]live.AddCasterProgramEpisode, 0, 1)
    	episode = append(episode, live.AddCasterProgramEpisode{
    		EpisodeType: "Resource",
    		EpisodeName: mezzanineInfoResp.Mezzanine.FileName,
    		ResourceId:  resourceID,
    		StartTime:   startTime,
    		EndTime:     endTime,
    		SwitchType:  "TimeFirst", // ContentFirst
    	})
    	program := live.CreateAddCasterProgramRequest()
    	program.Episode = &episode
    	program.CasterId = casterID
    	_, err = liveClient.AddCasterProgram(program)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    	// 启动导播台
    	startCasterRequest := live.CreateStartCasterRequest()
    	startCasterRequest.CasterId = casterID
    	_, err = liveClient.StartCaster(startCasterRequest)
    	if err != nil {
    		t.Fatal(err)
    	}
    }