Demo for virtual studio
A complete, runnable demo for managing a virtual studio by calling ApsaraVideo Live API operations.
API workflow
The virtual studio management workflow follows this sequence:
Add a video resource before you add a layout. Otherwise, the layout does not take effect.
Related operations:
Sample code
For API reference, see Production Studio API overview.
For SDK setup, see Go SDK Usage Instructions.
-
Create a production studio
// Create a production studio. func CreateCaster(liveClient *live20161101.Client) (*live20161101.CreateCasterResponse, error) { // The request parameters for creating a production studio. createCasterRequest := &live20161101.CreateCasterRequest{} createCasterRequest.ClientToken = tea.String(uuid.New().String()) createCasterRequest.CasterName = tea.String("Production studio for testing") createCasterRequest.ChargeType = tea.String("PostPaid") createCasterRequest.NormType = tea.Int32(1) createCasterResponse, err := liveClient.CreateCaster(createCasterRequest) if err != nil { return nil, errors.New("CreateCaster failed: " + err.Error()) } return createCasterResponse, nil }For request parameters, see CreateCaster.
-
Configure the production studio
// Configure the production studio. func SetCasterConfig(liveClient *live20161101.Client, casterId *string, domainName *string) (*live20161101.SetCasterConfigResponse, error) { // The parameters for configuring the production studio. createSetCasterConfig := &live20161101.SetCasterConfigRequest{} createSetCasterConfig.CasterId = casterId createSetCasterConfig.CasterName = tea.String("Production studio for testing") createSetCasterConfig.ChannelEnable = tea.Int32(1) createSetCasterConfig.Delay = tea.Float32(0) createSetCasterConfig.DomainName = domainName createSetCasterConfig.ProgramEffect = tea.Int32(1) createSetCasterConfig.ProgramName = tea.String("test loop play") // Transcoding settings (screen orientation and definition). // The CasterTemplate parameter can be set to the following values: lp_ld (low definition), lp_sd (standard definition), lp_hd (high definition), or lp_ud (ultra-high definition). lp_ld_v (low definition in portrait mode), lp_sd_v (standard definition in portrait mode), lp_hd_v (high definition in portrait mode), or lp_ud_v (ultra-high definition in portrait mode). createSetCasterConfig.TranscodeConfig = tea.String(`{"CasterTemplate": "lp_ld"}`) // Configure the recording parameters for the production studio. For more information about the JSON fields, see AddLiveAppRecordConfig. // createSetCasterConfig.RecordConfig = tea.String(`{ "endpoint": "", "ossBucket": "", "videoFormat": [{"format": "flv", "interval": 900, "prefix":"record/{AppName}/{StreamName}/{StartTime}_{EndTime}" }]}`) setCasterConfigResponse, err := liveClient.SetCasterConfig(createSetCasterConfig) if err != nil { return nil, errors.New("SetCasterConfig failed: " + err.Error()) } return setCasterConfigResponse, nil }For parameter details, see Configure a production studio.
-
Add a video resource
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } addCasterVideoResourceRequest := &live20161101.AddCasterVideoResourceRequest{ RegionId: tea.String("<Your RegionId>"), CasterId: tea.String("<Your CasterId>"), ResourceName: tea.String("<Your ResourceName>"), LiveStreamUrl: tea.String("<Your LiveStreamUrl>"), MaterialId: tea.String("<Your MaterialId>"), VodUrl: tea.String("<Your VodUrl>"), ImageId: tea.String("<Your ImageId>"), ImageUrl: tea.String("<Your ImageUrl>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.AddCasterVideoResourceWithOptions(addCasterVideoResourceRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For parameter details, see AddCasterVideoResource.
-
Add a virtual studio layout
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } addStudioLayoutRequest := &live20161101.AddStudioLayoutRequest{ RegionId: tea.String("<Your RegionId>"), CasterId: tea.String("<Your CasterId>"), LayoutName: tea.String("<Your LayoutName>"), LayoutType: tea.String("<Your LayoutType>"), CommonConfig: tea.String("<Your CommonConfig>"), BgImageConfig: tea.String("<Your BgImageConfig>"), ScreenInputConfigList: tea.String("<Your ScreenInputConfigList>"), MediaInputConfigList: tea.String("<Your MediaInputConfigList>"), LayerOrderConfigList: tea.String("<Your LayerOrderConfigList>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.AddStudioLayoutWithOptions(addStudioLayoutRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For more information about the AddStudioLayout operation, see AddStudioLayout.
-
Start the production studio and set the playback scene
package caster import ( "github.com/aliyun/alibaba-cloud-sdk-go/services/live" "github.com/go-ini/ini" "testing" "time" ) // Start the production studio and set the playback scenes. func StartCaster(t *testing.T) { cfg, err := ini.Load("conf/config.ini") if err != nil { t.Fatal(err) } // An AccessKey pair of an Alibaba Cloud account has permissions to call all API operations. We recommend that you use a RAM user to call API operations or perform O&M. // Do not hard-code the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of all resources in your account may be compromised. // In this example, the AccessKey pair is read from a configuration file for identity verification. For more information about how to configure the file, see ApsaraVideo Live > Development Reference > SDK Reference > Server-side SDKs > Go SDK. accessKeyID := cfg.Section("").Key("access_key_id").String() accessKeySecret := cfg.Section("").Key("access_key_secret").String() liveClient, err := live.NewClientWithAccessKey("cn-shanghai", accessKeyID, accessKeySecret) if err != nil { t.Fatal(err) } // Start the production studio. startCasterRequest := live.CreateStartCasterRequest() startCasterRequest.CasterId = "xxx" startCasterResp, err := liveClient.StartCaster(startCasterRequest) if err != nil { t.Fatal(err) } // Pause the process for a moment. It takes time to load resources. If you start the production studio immediately, the resources may fail to be loaded. time.Sleep(time.Second) // Set the playback scenes. // PVW (Optional) 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 (Required) setCasterSceneConfigRequest.SceneId = startCasterResp.PgmSceneInfos.SceneInfo[0].SceneId _, err = liveClient.SetCasterSceneConfig(setCasterSceneConfigRequest) if err != nil { t.Fatal(err) } }For the StartCaster API reference, see StartCaster.
For the SetCasterSceneConfig API reference, see SetCasterSceneConfig.
-
Update the scene configuration of the production studio
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials. credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } updateCasterSceneConfigRequest := &live20161101.UpdateCasterSceneConfigRequest{ RegionId: tea.String("<Your RegionId>"), ComponentId: []*string{tea.String("")}, CasterId: tea.String("<Your CasterId>"), SceneId: tea.String("<Your SceneId>"), LayoutId: tea.String("<Your LayoutId>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.UpdateCasterSceneConfigWithOptions(updateCasterSceneConfigRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For more information about the request parameters for the UpdateCasterSceneConfig operation, see UpdateCasterSceneConfig.
-
Stop the production studio
// Stop the production studio. func StopCaster(liveClient *live20161101.Client, casterId *string) error { stopCasterRequest := &live20161101.StopCasterRequest{ CasterId: casterId, } _, err := liveClient.StopCaster(stopCasterRequest) if err != nil { return errors.New("StopCaster failed: " + err.Error()) } return nil }For the StopCaster API reference, see StopCaster.
-
Delete a virtual studio layout
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } deleteStudioLayoutRequest := &live20161101.DeleteStudioLayoutRequest{ RegionId: tea.String("<Your RegionId>"), CasterId: tea.String("<Your CasterId>"), LayoutId: tea.String("<Your LayoutId>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.DeleteStudioLayoutWithOptions(deleteStudioLayoutRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For more information about the DeleteStudioLayout operation, see DeleteStudioLayout.
-
Delete the production studio
// Delete the production studio. func DeleteCaster(liveClient *live20161101.Client, casterId *string) error { deleteCasterRequest := &live20161101.DeleteCasterRequest{ CasterId: casterId, } _, err := liveClient.DeleteCaster(deleteCasterRequest) if err != nil { return errors.New("DeleteCaster failed: " + err.Error()) } return nil }For the DeleteCaster API reference, see DeleteCaster.
-
Modify a virtual studio layout
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } modifyStudioLayoutRequest := &live20161101.ModifyStudioLayoutRequest{ RegionId: tea.String("<Your RegionId>"), CasterId: tea.String("<Your CasterId>"), LayoutId: tea.String("<Your LayoutId>"), LayoutName: tea.String("<Your LayoutName>"), CommonConfig: tea.String("<Your CommonConfig>"), BgImageConfig: tea.String("<Your BgImageConfig>"), ScreenInputConfigList: tea.String("<Your ScreenInputConfigList>"), MediaInputConfigList: tea.String("<Your MediaInputConfigList>"), LayerOrderConfigList: tea.String("<Your LayerOrderConfigList>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.ModifyStudioLayoutWithOptions(modifyStudioLayoutRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For more information about the ModifyStudioLayout operation, see ModifyStudioLayout.
-
Query virtual studio layouts
// This file is auto-generated, don't edit it. Thanks. package main import ( "encoding/json" "strings" "fmt" "os" live20161101 "github.com/alibabacloud-go/live-20161101/v2/client" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" util "github.com/alibabacloud-go/tea-utils/v2/service" credential "github.com/aliyun/credentials-go/credentials" "github.com/alibabacloud-go/tea/tea" ) // Description: // // Use a credential to initialize a client. // // @return Client // // @throws Exception func CreateClient () (_result *live20161101.Client, _err error) { // We recommend that you use a credential-free method in your project for better security. For more information about how to configure credentials, see https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-go-access-credentials credential, _err := credential.NewCredential(nil) if _err != nil { return _result, _err } config := &openapi.Config{ Credential: credential, } // For more information about endpoints, see https://api.alibabacloud.com/product/live. config.Endpoint = tea.String("live.aliyuncs.com") _result = &live20161101.Client{} _result, _err = live20161101.NewClient(config) return _result, _err } func _main (args []*string) (_err error) { client, _err := CreateClient() if _err != nil { return _err } describeStudioLayoutsRequest := &live20161101.DescribeStudioLayoutsRequest{ RegionId: tea.String("<Your RegionId>"), } runtime := &util.RuntimeOptions{} tryErr := func()(_e error) { defer func() { if r := tea.Recover(recover()); r != nil { _e = r } }() // If you copy the code to run it, print the return value of the API operation. _, _err = client.DescribeStudioLayoutsWithOptions(describeStudioLayoutsRequest, runtime) if _err != nil { return _err } return nil }() if tryErr != nil { var error = &tea.SDKError{} if _t, ok := tryErr.(*tea.SDKError); ok { error = _t } else { error.Message = tea.String(tryErr.Error()) } // This is for demonstration purposes only. Handle exceptions with caution. Do not ignore exceptions in your projects. // Error message fmt.Println(tea.StringValue(error.Message)) // Diagnostic address var data interface{} d := json.NewDecoder(strings.NewReader(tea.StringValue(error.Data))) d.Decode(&data) if m, ok := data.(map[string]interface{}); ok { recommend, _ := m["Recommend"] fmt.Println(recommend) } _, _err = util.AssertAsString(error.Message) if _err != nil { return _err } } return _err } func main() { err := _main(tea.StringSlice(os.Args[1:])) if err != nil { panic(err) } }For more information about the DescribeStudioLayouts operation, see DescribeStudioLayouts.