From c8dfe74fc07276ffa8beae276a1a1efef30fba05 Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 17:05:52 +0800 Subject: [PATCH 1/9] vod update --- ...vod_adaptive_dynamic_streaming_template.go | 233 +++++++++-- ...vod_adaptive_dynamic_streaming_template.md | 40 +- ...daptive_dynamic_streaming_template_test.go | 48 ++- .../resource_tc_vod_image_sprite_template.go | 94 ++++- .../resource_tc_vod_image_sprite_template.md | 11 +- ...ource_tc_vod_image_sprite_template_test.go | 38 +- .../vod/resource_tc_vod_procedure_template.go | 374 ++++++++++++++++++ .../vod/resource_tc_vod_procedure_template.md | 77 +++- ...resource_tc_vod_procedure_template_test.go | 217 +++++++++- ...esource_tc_vod_sample_snapshot_template.go | 19 +- ...esource_tc_vod_sample_snapshot_template.md | 2 +- ...tc_vod_snapshot_by_time_offset_template.go | 82 +++- ...tc_vod_snapshot_by_time_offset_template.md | 4 +- ...d_snapshot_by_time_offset_template_test.go | 48 ++- .../services/vod/service_tencentcloud_vod.go | 13 +- 15 files changed, 1147 insertions(+), 153 deletions(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go index af14e6810f..cd72ac8cf2 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go @@ -5,12 +5,14 @@ import ( "fmt" "log" "strconv" + "strings" "time" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" vod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" @@ -123,6 +125,40 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource ValidateFunc: tccommon.ValidateAllowedStringValue([]string{"stretch", "black"}), Description: "Fill type. Fill refers to the way of processing a screenshot when its aspect ratio is different from that of the source video. The following fill types are supported: `stretch`: stretch. The screenshot will be stretched frame by frame to match the aspect ratio of the source video, which may make the screenshot shorter or longer; `black`: fill with black. This option retains the aspect ratio of the source video for the screenshot and fills the unmatched area with black color blocks. Default value: black. Note: this field may return null, indicating that no valid values can be obtained.", }, + "vcrf": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "Video constant bit rate control factor, value range is [1,51].\n" + + "Note:\n" + + "- If this parameter is specified, the bitrate control method of CRF will be used for transcoding (the video bitrate will no longer take effect);\n" + + "- This field is required when the video stream encoding format is H.266. The recommended value is 28;\n" + + "- If there are no special requirements, it is not recommended to specify this parameter.", + }, + "gop": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "Interval between Keyframe I frames, value range: 0 and [1, 100000], unit: number of frames. When you fill in 0 or leave it empty, the gop length is automatically set.", + }, + "preserve_hdr_switch": { + Type: schema.TypeString, + Optional: true, + Default: "OFF", + Description: "Whether the transcoding output still maintains HDR when the original video is HDR (High Dynamic Range). Value range:\n" + + "- ON: if the original file is HDR, the transcoding output remains HDR;, otherwise the transcoding output is SDR (Standard Dynamic Range);\n" + + "- OFF: regardless of whether the original file is HDR or SDR, the transcoding output is SDR;\n" + + "Default value: OFF.", + }, + "codec_tag": { + Type: schema.TypeString, + Optional: true, + Default: "hvc1", + Description: "Encoding label, valid only if the encoding format of the video stream is H.265 encoding. Available values:\n" + + "- hvc1: stands for hvc1 tag;\n" + + "- hev1: stands for the hev1 tag;\n" + + "Default value: hvc1.", + }, }, }, }, @@ -164,6 +200,37 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource Default: false, Description: "Whether to remove audio stream. Valid values: `false`: no, `true`: yes. `false` by default.", }, + "remove_video": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to remove video stream. Valid values: `false`: no, `true`: yes. `false` by default.", + }, + "tehd_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + MinItems: 1, + Description: "Extremely fast HD transcoding parameters.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + Description: "Extreme high-speed HD type, available values:\n" + + "- TEHD-100: super high definition-100th;\n" + + "- OFF: turn off Ultra High definition.", + }, + "max_video_bitrate": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + Description: "Video bitrate limit, which is valid when Type specifies extreme speed HD type. If you leave it empty or enter 0, there is no video bitrate limit.", + }, + }, + }, + }, }, }, }, @@ -200,26 +267,47 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res if v, ok := d.GetOk("comment"); ok { request.Comment = helper.String(v.(string)) } + var resourceId string if v, ok := d.GetOk("sub_app_id"); ok { - request.SubAppId = helper.IntUint64(v.(int)) + subAppId := v.(int) + resourceId += helper.IntToStr(subAppId) + resourceId += tccommon.FILED_SP + request.SubAppId = helper.IntUint64(subAppId) } streamInfos := d.Get("stream_info").([]interface{}) request.StreamInfos = make([]*vod.AdaptiveStreamTemplate, 0, len(streamInfos)) - for _, item := range streamInfos { + for idx, item := range streamInfos { v := item.(map[string]interface{}) video := v["video"].([]interface{})[0].(map[string]interface{}) audio := v["audio"].([]interface{})[0].(map[string]interface{}) rAudio := REMOVE_AUDIO_TO_UNINT[v["remove_audio"].(bool)] + rVideo := REMOVE_AUDIO_TO_UNINT[v["remove_video"].(bool)] + videoTemplateInfo := &vod.VideoTemplateInfo{ + Codec: helper.String(video["codec"].(string)), + Fps: helper.IntUint64(video["fps"].(int)), + Bitrate: helper.IntUint64(video["bitrate"].(int)), + ResolutionAdaptive: helper.String(RESOLUTION_ADAPTIVE_TO_STRING[video["resolution_adaptive"].(bool)]), + Width: helper.IntUint64(video["width"].(int)), + Height: helper.IntUint64(video["height"].(int)), + FillType: helper.String(video["fill_type"].(string)), + Vcrf: helper.IntUint64(video["vcrf"].(int)), + Gop: helper.IntUint64(video["gop"].(int)), + PreserveHDRSwitch: helper.String(video["preserve_hdr_switch"].(string)), + CodecTag: helper.String(video["codec_tag"].(string)), + } + if v, ok := d.GetOkExists(fmt.Sprintf("stream_info.%d.vcrf", idx)); ok { + videoTemplateInfo.Vcrf = helper.IntUint64(v.(int)) + } + if v, ok := d.GetOkExists(fmt.Sprintf("stream_info.%d.gop", idx)); ok { + videoTemplateInfo.Gop = helper.IntUint64(v.(int)) + } + var tehdConfig map[string]interface{} + if len(v["tehd_config"].([]interface{})) > 0 { + tehdConfig = v["tehd_config"].([]interface{})[0].(map[string]interface{}) + } request.StreamInfos = append(request.StreamInfos, &vod.AdaptiveStreamTemplate{ - Video: &vod.VideoTemplateInfo{ - Codec: helper.String(video["codec"].(string)), - Fps: helper.IntUint64(video["fps"].(int)), - Bitrate: helper.IntUint64(video["bitrate"].(int)), - ResolutionAdaptive: helper.String(RESOLUTION_ADAPTIVE_TO_STRING[video["resolution_adaptive"].(bool)]), - Width: helper.IntUint64(video["width"].(int)), - Height: helper.IntUint64(video["height"].(int)), - FillType: helper.String(video["fill_type"].(string)), - }, + + Video: videoTemplateInfo, Audio: &vod.AudioTemplateInfo{ Codec: helper.String(audio["codec"].(string)), Bitrate: helper.IntUint64(audio["bitrate"].(int)), @@ -227,6 +315,16 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res AudioChannel: helper.Int64(VOD_AUDIO_CHANNEL_TYPE_TO_INT[audio["audio_channel"].(string)]), }, RemoveAudio: &rAudio, + RemoveVideo: &rVideo, + TEHDConfig: func() *vod.TEHDConfig { + if tehdConfig == nil { + return nil + } + return &vod.TEHDConfig{ + Type: helper.String(tehdConfig["type"].(string)), + MaxVideoBitrate: helper.IntUint64(tehdConfig["max_video_bitrate"].(int)), + } + }(), }) } @@ -236,8 +334,13 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res ratelimit.Check(request.GetAction()) response, err = meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVodClient().CreateAdaptiveDynamicStreamingTemplate(request) if err != nil { - log.Printf("[CRITAL]%s api[%s] fail, reason:%s", logId, request.GetAction(), err.Error()) - return tccommon.RetryError(err) + if sdkError, ok := err.(*sdkErrors.TencentCloudSDKError); ok { + if sdkError.Code == "FailedOperation" && sdkError.Message == "invalid vod user" { + return resource.RetryableError(err) + } + } + log.Printf("[CRITAL]%s api[%s] fail, reason:%s", logId, request.GetAction(), strconv.ErrRange.Error()) + return resource.NonRetryableError(err) } return nil }) @@ -247,7 +350,8 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res if response == nil || response.Response == nil { return fmt.Errorf("for vod adaptive dynamic streaming template creation, response is nil") } - d.SetId(strconv.FormatUint(*response.Response.Definition, 10)) + resourceId += strconv.FormatUint(*response.Response.Definition, 10) + d.SetId(resourceId) return resourceTencentCloudVodAdaptiveDynamicStreamingTemplateRead(d, meta) } @@ -259,14 +363,21 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateRead(d *schema.Resou var ( logId = tccommon.GetLogId(tccommon.ContextNil) ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id = d.Id() - subAppId = d.Get("sub_app_id").(int) + subAppId int + definition string client = meta.(tccommon.ProviderMeta).GetAPIV3Conn() vodService = VodService{client: client} ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + } // waiting for refreshing cache time.Sleep(30 * time.Second) - template, has, err := vodService.DescribeAdaptiveDynamicStreamingTemplatesById(ctx, id, subAppId) + template, has, err := vodService.DescribeAdaptiveDynamicStreamingTemplatesById(ctx, definition, subAppId) if err != nil { return err } @@ -296,6 +407,10 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateRead(d *schema.Resou "width": v.Video.Width, "height": v.Video.Height, "fill_type": v.Video.FillType, + "vcrf": v.Video.Vcrf, + "gop": v.Video.Gop, + "preserve_hdr_switch": v.Video.PreserveHDRSwitch, + "codec_tag": v.Video.CodecTag, }, }, "audio": []map[string]interface{}{ @@ -307,9 +422,24 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateRead(d *schema.Resou }, }, "remove_audio": *v.RemoveAudio == 1, + "remove_video": *v.RemoveVideo == 1, + "tehd_config": func() []map[string]interface{} { + if v.TEHDConfig == nil { + return nil + } + return []map[string]interface{}{ + { + "type": v.TEHDConfig.Type, + "max_video_bitrate": v.TEHDConfig.MaxVideoBitrate, + }, + } + }(), }) } _ = d.Set("stream_info", streamInfos) + if subAppId != 0 { + _ = d.Set("sub_app_id", subAppId) + } return nil } @@ -320,12 +450,33 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res var ( logId = tccommon.GetLogId(tccommon.ContextNil) request = vod.NewModifyAdaptiveDynamicStreamingTemplateRequest() - id = d.Id() changeFlag = false + subAppId int + definition string ) - idUint, _ := strconv.ParseUint(id, 0, 64) - request.Definition = &idUint + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + request.SubAppId = helper.IntUint64(subAppId) + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + request.SubAppId = helper.IntUint64(v.(int)) + } + } + + request.Definition = helper.StrToUint64Point(definition) + + immutableArgs := []string{"sub_app_id"} + + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) + } + } + if d.HasChange("format") { changeFlag = true request.Format = helper.String(d.Get("format").(string)) @@ -346,10 +497,6 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res changeFlag = true request.Comment = helper.String(d.Get("comment").(string)) } - if d.HasChange("sub_app_id") { - changeFlag = true - request.SubAppId = helper.IntUint64(d.Get("sub_app_id").(int)) - } if d.HasChange("stream_info") { changeFlag = true streamInfos := d.Get("stream_info").([]interface{}) @@ -358,7 +505,12 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res v := item.(map[string]interface{}) video := v["video"].([]interface{})[0].(map[string]interface{}) audio := v["audio"].([]interface{})[0].(map[string]interface{}) + var tehdConfig map[string]interface{} + if len(v["tehd_config"].([]interface{})) > 0 { + tehdConfig = v["tehd_config"].([]interface{})[0].(map[string]interface{}) + } rAudio := REMOVE_AUDIO_TO_UNINT[v["remove_audio"].(bool)] + rVideo := REMOVE_AUDIO_TO_UNINT[v["remove_video"].(bool)] request.StreamInfos = append(request.StreamInfos, &vod.AdaptiveStreamTemplate{ Video: &vod.VideoTemplateInfo{ Codec: helper.String(video["codec"].(string)), @@ -377,7 +529,11 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res } return helper.IntUint64(height) }(video["height"].(int)), - FillType: helper.String(video["fill_type"].(string)), + FillType: helper.String(video["fill_type"].(string)), + Vcrf: helper.IntUint64(video["vcrf"].(int)), + Gop: helper.IntUint64(video["gop"].(int)), + PreserveHDRSwitch: helper.String(video["preserve_hdr_switch"].(string)), + CodecTag: helper.String(video["codec_tag"].(string)), }, Audio: &vod.AudioTemplateInfo{ Codec: helper.String(audio["codec"].(string)), @@ -386,6 +542,16 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res AudioChannel: helper.Int64(VOD_AUDIO_CHANNEL_TYPE_TO_INT[audio["audio_channel"].(string)]), }, RemoveAudio: &rAudio, + RemoveVideo: &rVideo, + TEHDConfig: func() *vod.TEHDConfig { + if tehdConfig == nil { + return nil + } + return &vod.TEHDConfig{ + Type: helper.String(tehdConfig["type"].(string)), + MaxVideoBitrate: helper.IntUint64(tehdConfig["max_video_bitrate"].(int)), + } + }(), }) } } @@ -417,12 +583,25 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateDelete(d *schema.Res logId := tccommon.GetLogId(tccommon.ContextNil) ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id := d.Id() + var ( + subAppId int + definition string + ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + subAppId = v.(int) + } + } vodService := VodService{ client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), } - if err := vodService.DeleteAdaptiveDynamicStreamingTemplate(ctx, id, uint64(d.Get("sub_app_id").(int))); err != nil { + if err := vodService.DeleteAdaptiveDynamicStreamingTemplate(ctx, definition, uint64(subAppId)); err != nil { return err } diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.md b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.md index 487b9c6c04..7644293cea 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.md +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.md @@ -3,52 +3,44 @@ Provide a resource to create a VOD adaptive dynamic streaming template. Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "adaptive-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = false disable_higher_video_resolution = false comment = "test" - stream_info { - video { - codec = "libx265" - fps = 4 - bitrate = 129 - resolution_adaptive = false - width = 128 - height = 128 - fill_type = "stretch" - } - audio { - codec = "libmp3lame" - bitrate = 129 - sample_rate = 44100 - audio_channel = "dual" - } - remove_audio = false - } stream_info { video { codec = "libx264" - fps = 4 - bitrate = 256 + fps = 3 + bitrate = 128 } audio { codec = "libfdk_aac" - bitrate = 256 - sample_rate = 44100 + bitrate = 128 + sample_rate = 32000 } remove_audio = true + tehd_config { + type = "TEHD-100" + } } } ``` Import -VOD adaptive dynamic streaming template can be imported using the id, e.g. +VOD adaptive dynamic streaming template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_adaptive_dynamic_streaming_template.foo 169141 +$ terraform import tencentcloud_vod_adaptive_dynamic_streaming_template.foo $subAppId#$templateId ``` \ No newline at end of file diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go index 7ab4ae3b60..59ec1ec241 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template_test.go @@ -4,10 +4,12 @@ import ( "context" "fmt" "strconv" + "strings" "testing" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" svcvod "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/vod" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -53,7 +55,6 @@ func TestAccTencentCloudVodAdaptiveDynamicStreamingTemplateResource(t *testing.T { Config: testAccVodAdaptiveDynamicStreamingTemplate, Check: resource.ComposeTestCheckFunc( - testAccCheckVodAdaptiveDynamicStreamingTemplateExists("tencentcloud_vod_adaptive_dynamic_streaming_template.foo"), resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "format", "HLS"), resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "name", "tf-adaptive"), resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "drm_type", "SimpleAES"), @@ -81,6 +82,7 @@ func TestAccTencentCloudVodAdaptiveDynamicStreamingTemplateResource(t *testing.T resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "stream_info.1.remove_audio", "true"), resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "create_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "update_time"), + resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "sub_app_id"), ), }, { @@ -104,13 +106,14 @@ func TestAccTencentCloudVodAdaptiveDynamicStreamingTemplateResource(t *testing.T resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "stream_info.0.audio.0.sample_rate", "44100"), resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "stream_info.0.audio.0.audio_channel", "dual"), resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "stream_info.0.remove_audio", "false"), + resource.TestCheckResourceAttrSet("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "sub_app_id"), + resource.TestCheckResourceAttr("tencentcloud_vod_adaptive_dynamic_streaming_template.foo", "stream_info.0.tehd_config.0.type", "TEHD-100"), ), }, { - ResourceName: "tencentcloud_vod_adaptive_dynamic_streaming_template.foo", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"sub_app_id"}, + ResourceName: "tencentcloud_vod_adaptive_dynamic_streaming_template.foo", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -125,11 +128,13 @@ func testAccCheckVodAdaptiveDynamicStreamingTemplateDestroy(s *terraform.State) if rs.Type != "tencentcloud_vod_adaptive_dynamic_streaming_template" { continue } - var ( - filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, - } - ) + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] + filter := map[string]interface{}{ + "definitions": []string{definition}, + "sub_appid": subAppId, + } templates, err := vodService.DescribeAdaptiveDynamicStreamingTemplatesByFilter(ctx, filter) if err != nil { @@ -156,9 +161,13 @@ func testAccCheckVodAdaptiveDynamicStreamingTemplateExists(n string) resource.Te return fmt.Errorf("vod adaptive dynamic streaming template id is not set") } vodService := svcvod.NewVodService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] var ( filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, + "definitions": []string{definition}, + "sub_appid": subAppId, } ) @@ -174,9 +183,16 @@ func testAccCheckVodAdaptiveDynamicStreamingTemplateExists(n string) resource.Te } const testAccVodAdaptiveDynamicStreamingTemplate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "adaptive-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = false disable_higher_video_resolution = false @@ -212,9 +228,16 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { ` const testAccVodAdaptiveDynamicStreamingTemplateUpdate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "adaptive-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive-update" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = true disable_higher_video_resolution = true @@ -237,6 +260,9 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { audio_channel = "dual" } remove_audio = false + tehd_config { + type = "TEHD-100" + } } } ` diff --git a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go index bfa6c9fb0f..c040520e37 100644 --- a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" @@ -90,6 +91,16 @@ func ResourceTencentCloudVodImageSpriteTemplate() *schema.Resource { Optional: true, Description: "Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty.", }, + "format": { + Type: schema.TypeString, + Optional: true, + Default: "jpg", + Description: "Image format, Valid values:\n" + + "- jpg: jpg format;\n" + + "- png: png format;\n" + + "- webp: webp format;\n" + + "Default value: jpg.", + }, // computed "create_time": { Type: schema.TypeString, @@ -101,6 +112,13 @@ func ResourceTencentCloudVodImageSpriteTemplate() *schema.Resource { Computed: true, Description: "Last modified time of template in ISO date format.", }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: "Template type, value range:\n" + + "- Preset: system preset template;\n" + + "- Custom: user-defined templates.", + }, }, } } @@ -125,8 +143,15 @@ func resourceTencentCloudVodImageSpriteTemplateCreate(d *schema.ResourceData, me request.Width = helper.IntUint64(d.Get("width").(int)) request.Height = helper.IntUint64(d.Get("height").(int)) request.ResolutionAdaptive = helper.String(RESOLUTION_ADAPTIVE_TO_STRING[d.Get("resolution_adaptive").(bool)]) + var resourceId string if v, ok := d.GetOk("sub_app_id"); ok { - request.SubAppId = helper.IntUint64(v.(int)) + subAppId := v.(int) + resourceId += helper.IntToStr(subAppId) + resourceId += tccommon.FILED_SP + request.SubAppId = helper.IntUint64(subAppId) + } + if v, ok := d.GetOk("format"); ok { + request.Format = helper.String(v.(string)) } var response *vod.CreateImageSpriteTemplateResponse @@ -146,7 +171,8 @@ func resourceTencentCloudVodImageSpriteTemplateCreate(d *schema.ResourceData, me if response == nil || response.Response == nil { return fmt.Errorf("for image sprite template creation, response is nil") } - d.SetId(strconv.FormatUint(*response.Response.Definition, 10)) + resourceId += strconv.FormatUint(*response.Response.Definition, 10) + d.SetId(resourceId) return resourceTencentCloudVodImageSpriteTemplateRead(d, meta) } @@ -158,14 +184,21 @@ func resourceTencentCloudVodImageSpriteTemplateRead(d *schema.ResourceData, meta var ( logId = tccommon.GetLogId(tccommon.ContextNil) ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id = d.Id() - subAppId = d.Get("sub_app_id").(int) + subAppId int + definition string client = meta.(tccommon.ProviderMeta).GetAPIV3Conn() vodService = VodService{client: client} ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + } // waiting for refreshing cache time.Sleep(30 * time.Second) - template, has, err := vodService.DescribeImageSpriteTemplatesById(ctx, id, subAppId) + template, has, err := vodService.DescribeImageSpriteTemplatesById(ctx, definition, subAppId) if err != nil { return err } @@ -186,6 +219,11 @@ func resourceTencentCloudVodImageSpriteTemplateRead(d *schema.ResourceData, meta _ = d.Set("resolution_adaptive", *template.ResolutionAdaptive == "open") _ = d.Set("create_time", template.CreateTime) _ = d.Set("update_time", template.UpdateTime) + _ = d.Set("format", template.Format) + _ = d.Set("type", template.Type) + if subAppId != 0 { + _ = d.Set("sub_app_id", subAppId) + } return nil } @@ -196,12 +234,31 @@ func resourceTencentCloudVodImageSpriteTemplateUpdate(d *schema.ResourceData, me var ( logId = tccommon.GetLogId(tccommon.ContextNil) request = vod.NewModifyImageSpriteTemplateRequest() - id = d.Id() changeFlag = false + subAppId int + definition string ) - idUint, _ := strconv.ParseUint(id, 0, 64) - request.Definition = &idUint + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + request.SubAppId = helper.IntUint64(subAppId) + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + request.SubAppId = helper.IntUint64(v.(int)) + } + } + request.Definition = helper.StrToUint64Point(definition) + immutableArgs := []string{"sub_app_id"} + + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) + } + } + if d.HasChange("sample_type") { changeFlag = true request.SampleType = helper.String(d.Get("sample_type").(string)) @@ -236,9 +293,9 @@ func resourceTencentCloudVodImageSpriteTemplateUpdate(d *schema.ResourceData, me request.Height = helper.IntUint64(d.Get("height").(int)) request.ResolutionAdaptive = helper.String(RESOLUTION_ADAPTIVE_TO_STRING[d.Get("resolution_adaptive").(bool)]) } - if d.HasChange("sub_app_id") { + if d.HasChange("format") { changeFlag = true - request.SubAppId = helper.IntUint64(d.Get("sub_app_id").(int)) + request.Format = helper.String(d.Get("format").(string)) } if changeFlag { @@ -268,12 +325,25 @@ func resourceTencentCloudVodImageSpriteTemplateDelete(d *schema.ResourceData, me logId := tccommon.GetLogId(tccommon.ContextNil) ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id := d.Id() + var ( + subAppId int + definition string + ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + subAppId = v.(int) + } + } vodService := VodService{ client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), } - if err := vodService.DeleteImageSpriteTemplate(ctx, id, uint64(d.Get("sub_app_id").(int))); err != nil { + if err := vodService.DeleteImageSpriteTemplate(ctx, definition, uint64(subAppId)); err != nil { return err } diff --git a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.md b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.md index d40212a128..75f64e9ce5 100644 --- a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.md +++ b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.md @@ -3,8 +3,15 @@ Provide a resource to create a VOD image sprite template. Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "image-sprite-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 10 row_count = 3 column_count = 3 @@ -19,8 +26,8 @@ resource "tencentcloud_vod_image_sprite_template" "foo" { Import -VOD image sprite template can be imported using the id, e.g. +VOD image sprite template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_image_sprite_template.foo 51156 +$ terraform import tencentcloud_vod_image_sprite_template.foo $subAppId#$templateId ``` \ No newline at end of file diff --git a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template_test.go b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template_test.go index 23b5cf0805..3a1fc1624d 100644 --- a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template_test.go @@ -3,10 +3,12 @@ package vod_test import ( "context" "fmt" + "strings" "testing" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" svcvod "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/vod" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -23,7 +25,6 @@ func TestAccTencentCloudVodImageSpriteTemplateResource(t *testing.T) { { Config: testAccVodImageSpriteTemplate, Check: resource.ComposeTestCheckFunc( - testAccCheckVodImageSpriteTemplateExists("tencentcloud_vod_image_sprite_template.foo"), resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "sample_type", "Percent"), resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "sample_interval", "10"), resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "row_count", "3"), @@ -34,8 +35,10 @@ func TestAccTencentCloudVodImageSpriteTemplateResource(t *testing.T) { resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "width", "128"), resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "height", "128"), resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "resolution_adaptive", "false"), + resource.TestCheckResourceAttr("tencentcloud_vod_image_sprite_template.foo", "format", "jpg"), resource.TestCheckResourceAttrSet("tencentcloud_vod_image_sprite_template.foo", "create_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_image_sprite_template.foo", "update_time"), + resource.TestCheckResourceAttrSet("tencentcloud_vod_image_sprite_template.foo", "type"), ), }, { @@ -54,10 +57,9 @@ func TestAccTencentCloudVodImageSpriteTemplateResource(t *testing.T) { ), }, { - ResourceName: "tencentcloud_vod_image_sprite_template.foo", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"sub_app_id"}, + ResourceName: "tencentcloud_vod_image_sprite_template.foo", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -72,9 +74,13 @@ func testAccCheckVodImageSpriteTemplateDestroy(s *terraform.State) error { if rs.Type != "tencentcloud_vod_image_sprite_template" { continue } + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] var ( filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, + "definitions": []string{definition}, + "sub_appid": subAppId, } ) @@ -103,9 +109,13 @@ func testAccCheckVodImageSpriteTemplateExists(n string) resource.TestCheckFunc { return fmt.Errorf("vod image sprite template id is not set") } vodService := svcvod.NewVodService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] var ( filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, + "definitions": []string{definition}, + "sub_appid": subAppId, } ) templates, err := vodService.DescribeImageSpriteTemplatesByFilter(ctx, filter) @@ -120,8 +130,15 @@ func testAccCheckVodImageSpriteTemplateExists(n string) resource.TestCheckFunc { } const testAccVodImageSpriteTemplate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "image-sprite-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 10 row_count = 3 column_count = 3 @@ -135,8 +152,15 @@ resource "tencentcloud_vod_image_sprite_template" "foo" { ` const testAccVodImageSpriteTemplateUpdate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "image-sprite-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Time" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 11 row_count = 4 column_count = 4 diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go index 7fb8897cea..2517e8d1e6 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go @@ -2,6 +2,7 @@ package vod import ( "context" + "fmt" "log" "strconv" "strings" @@ -121,6 +122,68 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { }, }, }, + "trace_watermark": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: "Digital watermark.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "switch": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Whether to use digital watermarks. This parameter is required. Valid values: ON, OFF.", + }, + }, + }, + }, + "copy_right_watermark": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: "opyright watermark.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "text": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Copyright information, maximum length is 200 characters.", + }, + }, + }, + }, + "head_tail_list": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "List of video opening/closing credits configuration template IDs. You can enter up to 10 IDs.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Video opening/closing credits configuration template ID.", + }, + }, + }, + }, + "start_time_offset": { + Type: schema.TypeFloat, + Optional: true, + Computed: true, + Description: "Start time offset of blur in seconds. If this parameter is left empty or `0` is entered, the blur will appear upon the first video frame. If this parameter is left empty or `0` is entered, the blur will appear upon the first video frame; If this value is greater than `0` (e.g., n), the blur will appear at second n after the first video frame; If this value is smaller than `0` (e.g., -n), the blur will appear at second n before the last video frame.", + }, + "end_time_offset": { + Type: schema.TypeFloat, + Optional: true, + Computed: true, + Description: "End time offset of blur in seconds. If this parameter is left empty or `0` is entered, the blur will exist till the last video frame; If this value is greater than `0` (e.g., n), the blur will exist till second n; If this value is smaller than `0` (e.g., -n), the blur will exist till second n before the last video frame.", + }, }, }, }, @@ -174,6 +237,15 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { Description: "List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained.", Elem: VodWatermarkResource(), }, + "time_offset_list": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "List of time points for screencapturing in milliseconds. Note: this field may return null, indicating that no valid values can be obtained.", + Elem: &schema.Schema{ + Type: schema.TypeFloat, + }, + }, }, }, }, @@ -268,6 +340,62 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { }, }, }, + "ai_analysis_task": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: "Parameter of AI-based content analysis task.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Video content analysis template ID.", + }, + }, + }, + }, + "ai_recognition_task": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: "Type parameter of AI-based content recognition task.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Intelligent video recognition template ID.", + }, + }, + }, + }, + "review_audio_video_task": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: "Type parameter of AI-based content recognition task.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "review_contents": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "The type of moderated content. Valid values:\n" + + "- `Media`: The original audio/video;\n" + + "- `Cover`: Thumbnails.", + }, + }, + }, + }, "create_time": { Type: schema.TypeString, Computed: true, @@ -278,6 +406,13 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { Computed: true, Description: "Last modified time of template in ISO date format.", }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: "Template type, value range:\n" + + "- Preset: system preset template;\n" + + "- Custom: user-defined templates.", + }, }, } } @@ -407,6 +542,68 @@ func generateMediaProcessTask(d *schema.ResourceData) (mediaReq *vod.MediaProces }(item["definition"].(string)), WatermarkSet: genWatermarkList(item), MosaicSet: genMosaicList(item), + TraceWatermark: func() *vod.TraceWatermarkInput { + if _, ok := item["trace_watermark"]; !ok { + return nil + } + traceWatermarks := item["trace_watermark"].([]interface{}) + if len(traceWatermarks) <= 0 { + return nil + } + traceWatermarkInput := &vod.TraceWatermarkInput{} + traceWatermarkItem := traceWatermarks[0].(map[string]interface{}) + if v, ok := traceWatermarkItem["switch"]; ok { + traceWatermarkInput.Switch = helper.String(v.(string)) + } + return traceWatermarkInput + }(), + CopyRightWatermark: func() *vod.CopyRightWatermarkInput { + if _, ok := item["copy_right_watermark"]; !ok { + return nil + } + copyRightWatermarks := item["copy_right_watermark"].([]interface{}) + if len(copyRightWatermarks) <= 0 { + return nil + } + + copyRightWatermarkInput := &vod.CopyRightWatermarkInput{} + copyRightWatermarkItem := copyRightWatermarks[0].(map[string]interface{}) + if vv, ok := copyRightWatermarkItem["text"]; ok { + copyRightWatermarkInput = &vod.CopyRightWatermarkInput{ + Text: helper.String(vv.(string)), + } + } + return copyRightWatermarkInput + }(), + HeadTailSet: func() (list []*vod.HeadTailTaskInput) { + if _, ok := item["head_tail_list"]; !ok { + return + } + headTailSet := item["head_tail_list"].([]interface{}) + list = make([]*vod.HeadTailTaskInput, 0, len(headTailSet)) + for _, headTail := range headTailSet { + headTailMap := headTail.(map[string]interface{}) + list = append(list, &vod.HeadTailTaskInput{ + Definition: func(str string) *int64 { + definition, _ := strconv.ParseInt(str, 0, 64) + return &definition + }(headTailMap["definition"].(string)), + }) + } + return + }(), + StartTimeOffset: func() *float64 { + if _, ok := item["start_time_offset"]; !ok { + return nil + } + return helper.Float64(item["start_time_offset"].(float64)) + }(), + EndTimeOffset: func() *float64 { + if _, ok := item["end_time_offset"]; !ok { + return nil + } + return helper.Float64(item["end_time_offset"].(float64)) + }(), }) } mediaReq.TranscodeTaskSet = transcodeReq @@ -451,6 +648,17 @@ func generateMediaProcessTask(d *schema.ResourceData) (mediaReq *vod.MediaProces } return list }(), + TimeOffsetSet: func() (list []*float64) { + if _, ok := item["time_offset_list"]; !ok { + return nil + } + timeOffsetSet := item["time_offset_list"].([]interface{}) + list = make([]*float64, 0, len(timeOffsetSet)) + for _, timeOffset := range timeOffsetSet { + list = append(list, helper.Float64(timeOffset.(float64))) + } + return list + }(), }) } mediaReq.SnapshotByTimeOffsetTaskSet = snapshotReq @@ -549,7 +757,44 @@ func resourceTencentCloudVodProcedureTemplateCreate(d *schema.ResourceData, meta mediaReq := generateMediaProcessTask(d) request.MediaProcessTask = mediaReq } + //ai_analysis_task + if aiAnalysisTask, ok := d.GetOk("ai_analysis_task"); ok { + aiAnalysisTaskList := aiAnalysisTask.([]interface{}) + aiAnalysisTaskItem := aiAnalysisTaskList[0].(map[string]interface{}) + request.AiAnalysisTask = &vod.AiAnalysisTaskInput{ + Definition: helper.StrToUint64Point(aiAnalysisTaskItem["definition"].(string)), + } + } + //ai_recognition_task + if aiRecognitionTask, ok := d.GetOk("ai_recognition_task"); ok { + aiRecognitionTaskList := aiRecognitionTask.([]interface{}) + aiRecognitionTaskItem := aiRecognitionTaskList[0].(map[string]interface{}) + + request.AiRecognitionTask = &vod.AiRecognitionTaskInput{ + Definition: helper.StrToUint64Point(aiRecognitionTaskItem["definition"].(string)), + } + } + //review_audio_video_task + if reviewAudioVideoTask, ok := d.GetOk("review_audio_video_task"); ok { + reviewAudioVideoTaskList := reviewAudioVideoTask.([]interface{}) + reviewAudioVideoTaskItem := reviewAudioVideoTaskList[0].(map[string]interface{}) + + request.ReviewAudioVideoTask = &vod.ProcedureReviewAudioVideoTaskInput{ + Definition: helper.StrToUint64Point(reviewAudioVideoTaskItem["definition"].(string)), + ReviewContents: func() (list []*string) { + if _, ok := reviewAudioVideoTaskItem["review_contents"]; !ok { + return + } + reviewContentList := reviewAudioVideoTaskItem["review_contents"].([]interface{}) + list = make([]*string, 0, len(reviewContentList)) + for _, reviewContent := range reviewContentList { + list = append(list, helper.String(reviewContent.(string))) + } + return + }(), + } + } var err error err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { ratelimit.Check(request.GetAction()) @@ -599,6 +844,7 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i } _ = d.Set("name", template.Name) + _ = d.Set("type", template.Type) _ = d.Set("comment", template.Comment) _ = d.Set("create_time", template.CreateTime) _ = d.Set("update_time", template.UpdateTime) @@ -648,6 +894,48 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i } return mosaicList }(), + "trace_watermark": func() interface{} { + if item.TraceWatermark == nil { + return nil + } + traceWatermark := map[string]interface{}{ + "switch": item.TraceWatermark.Switch, + } + return []interface{}{traceWatermark} + }(), + "copy_right_watermark": func() interface{} { + if item.CopyRightWatermark == nil { + return nil + } + copyRightWatermark := map[string]interface{}{ + "text": item.CopyRightWatermark.Text, + } + return []interface{}{copyRightWatermark} + }(), + "head_tail_list": func() interface{} { + if item.HeadTailSet == nil { + return nil + } + headTailList := make([]interface{}, 0, len(item.HeadTailSet)) + for _, headTail := range item.HeadTailSet { + headTailList = append(headTailList, map[string]interface{}{ + "definition": headTail.Definition, + }) + } + return headTailList + }(), + "start_time_offset": func() *float64 { + if item.StartTimeOffset == nil { + return nil + } + return item.StartTimeOffset + }(), + "end_time_offset": func() *float64 { + if item.EndTimeOffset == nil { + return nil + } + return item.EndTimeOffset + }(), }) } mediaProcessTaskElem["transcode_task_list"] = list @@ -696,6 +984,16 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i } return extList }(), + "time_offset_list": func() interface{} { + if item.TimeOffsetSet == nil { + return nil + } + timeOffsetList := make([]interface{}, 0, len(item.TimeOffsetSet)) + for _, timeOffset := range item.TimeOffsetSet { + timeOffsetList = append(timeOffsetList, timeOffset) + } + return timeOffsetList + }(), }) } mediaProcessTaskElem["snapshot_by_time_offset_task_list"] = list @@ -793,7 +1091,30 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i _ = d.Set("media_process_task", []interface{}{mediaProcessTaskElem}) } + aiAnalysisTask := make(map[string]interface{}) + if template.AiAnalysisTask != nil && template.AiAnalysisTask.Definition != nil { + aiAnalysisTask["definition"] = template.AiAnalysisTask.Definition + } + _ = d.Set("ai_analysis_task", []interface{}{aiAnalysisTask}) + aiRecognitionTask := make(map[string]interface{}) + if template.AiRecognitionTask != nil && template.AiRecognitionTask.Definition != nil { + aiRecognitionTask["definition"] = template.AiRecognitionTask.Definition + } + _ = d.Set("ai_recognition_task", []interface{}{aiRecognitionTask}) + reviewAudioVideoTask := make(map[string]interface{}) + if template.ReviewAudioVideoTask != nil { + if template.ReviewAudioVideoTask.Definition != nil { + reviewAudioVideoTask["definition"] = template.ReviewAudioVideoTask.Definition + } + if template.ReviewAudioVideoTask.ReviewContents != nil { + reviewContentList := make([]string, 0, len(template.ReviewAudioVideoTask.ReviewContents)) + for _, revireviewContent := range template.ReviewAudioVideoTask.ReviewContents { + reviewContentList = append(reviewContentList, *revireviewContent) + } + } + } + _ = d.Set("review_audio_video_task", []interface{}{reviewAudioVideoTask}) return nil } @@ -819,6 +1140,14 @@ func resourceTencentCloudVodProcedureTemplateUpdate(d *schema.ResourceData, meta } } + immutableArgs := []string{"sub_app_id"} + + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) + } + } + if d.HasChange("comment") { changeFlag = true request.Comment = helper.String(d.Get("comment").(string)) @@ -830,6 +1159,51 @@ func resourceTencentCloudVodProcedureTemplateUpdate(d *schema.ResourceData, meta request.MediaProcessTask = mediaReq } + if d.HasChange("ai_analysis_task") { + changeFlag = true + if aiAnalysisTask, ok := d.GetOk("ai_analysis_task"); ok { + aiAnalysisTaskList := aiAnalysisTask.([]interface{}) + aiAnalysisTaskItem := aiAnalysisTaskList[0].(map[string]interface{}) + + request.AiAnalysisTask = &vod.AiAnalysisTaskInput{ + Definition: helper.StrToUint64Point(aiAnalysisTaskItem["definition"].(string)), + } + } + } + + if d.HasChange("ai_recognition_task") { + changeFlag = true + if aiRecognitionTask, ok := d.GetOk("ai_recognition_task"); ok { + aiRecognitionTaskList := aiRecognitionTask.([]interface{}) + aiRecognitionTaskItem := aiRecognitionTaskList[0].(map[string]interface{}) + + request.AiRecognitionTask = &vod.AiRecognitionTaskInput{ + Definition: helper.StrToUint64Point(aiRecognitionTaskItem["definition"].(string)), + } + } + } + if d.HasChange("review_audio_video_task") { + changeFlag = true + if reviewAudioVideoTask, ok := d.GetOk("review_audio_video_task"); ok { + reviewAudioVideoTaskList := reviewAudioVideoTask.([]interface{}) + reviewAudioVideoTaskItem := reviewAudioVideoTaskList[0].(map[string]interface{}) + request.ReviewAudioVideoTask = &vod.ProcedureReviewAudioVideoTaskInput{ + Definition: helper.StrToUint64Point(reviewAudioVideoTaskItem["definition"].(string)), + ReviewContents: func() (list []*string) { + if _, ok := reviewAudioVideoTaskItem["review_contents"]; !ok { + return + } + reviewContentList := reviewAudioVideoTaskItem["review_contents"].([]interface{}) + list = make([]*string, 0, len(reviewContentList)) + for _, reviewContent := range reviewContentList { + list = append(list, helper.String(reviewContent.(string))) + } + return + }(), + } + } + } + if changeFlag { var err error err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template.md b/tencentcloud/services/vod/resource_tc_vod_procedure_template.md index 8ba2f1a452..0cff89e197 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template.md +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template.md @@ -3,9 +3,16 @@ Provide a resource to create a VOD procedure template. Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "procedure-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = false disable_higher_video_resolution = false @@ -13,21 +20,16 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { stream_info { video { - codec = "libx265" - fps = 4 - bitrate = 129 - resolution_adaptive = false - width = 128 - height = 128 - fill_type = "stretch" + codec = "libx264" + fps = 3 + bitrate = 128 } audio { - codec = "libmp3lame" - bitrate = 129 - sample_rate = 44100 - audio_channel = "dual" + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 32000 } - remove_audio = false + remove_audio = true } stream_info { video { @@ -41,12 +43,16 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { sample_rate = 44100 } remove_audio = true + tehd_config { + type = "TEHD-100" + } } } resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { name = "tf-snapshot" - width = 130 + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + width = 128 height = 128 resolution_adaptive = false format = "png" @@ -56,6 +62,7 @@ resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 10 row_count = 3 column_count = 3 @@ -67,28 +74,56 @@ resource "tencentcloud_vod_image_sprite_template" "foo" { resolution_adaptive = false } -resource "tencentcloud_vod_sub_application" "sub_application" { - name = "subapplication" - status = "On" - description = "this is sub application" +resource "tencentcloud_vod_transcode_template" "transcode_template" { + container = "mp4" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + name = "720pTranscodeTemplate" + comment = "test transcode mp4 720p update" + remove_video = 0 + remove_audio = 0 + video_template { + codec = "libx264" + fps = 26 + bitrate = 1000 + resolution_adaptive = "open" + width = 0 + height = 720 + fill_type = "stretch" + vcrf = 1 + gop = 250 + preserve_hdr_switch = "OFF" + codec_tag = "hvc1" + + } + audio_template { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 44100 + audio_channel = 2 + + } + segment_type = "ts" } resource "tencentcloud_vod_procedure_template" "foo" { - name = "tf-procedure" + name = "tf-procedure0" comment = "test" sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) media_process_task { adaptive_dynamic_streaming_task_list { - definition = tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id)[1]) } snapshot_by_time_offset_task_list { - definition = tencentcloud_vod_snapshot_by_time_offset_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_snapshot_by_time_offset_template.foo.id)[1]) ext_time_offset_list = [ "3.5s" ] } image_sprite_task_list { - definition = tencentcloud_vod_image_sprite_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_image_sprite_template.foo.id)[1]) + } + transcode_task_list { + definition = tonumber(split("#", tencentcloud_vod_transcode_template.transcode_template.id)[1]) } } } diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go index df8385cc41..744399529d 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go @@ -67,6 +67,7 @@ func TestAccTencentCloudVodProcedureTemplateResource(t *testing.T) { resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "media_process_task.0.adaptive_dynamic_streaming_task_list.0.definition"), resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "media_process_task.0.snapshot_by_time_offset_task_list.0.definition"), resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "media_process_task.0.image_sprite_task_list.0.definition"), + resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "media_process_task.0.transcode_task_list.0.definition"), resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "create_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_procedure_template.foo", "update_time"), ), @@ -160,56 +161,254 @@ func testAccCheckVodProcedureTemplateExists(n string) resource.TestCheckFunc { } } -const testAccVodProcedureTemplate = testAccVodAdaptiveDynamicStreamingTemplate + testAccVodSnapshotByTimeOffsetTemplate + testAccVodImageSpriteTemplate + ` +const testAccVodProcedureTemplate = ` resource "tencentcloud_vod_sub_application" "sub_application" { - name = "subapplication" + name = "procedure-subapplication" status = "On" description = "this is sub application" } +resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { + format = "HLS" + name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + drm_type = "SimpleAES" + disable_higher_video_bitrate = false + disable_higher_video_resolution = false + comment = "test" + + stream_info { + video { + codec = "libx264" + fps = 3 + bitrate = 128 + } + audio { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 32000 + } + remove_audio = true + } + stream_info { + video { + codec = "libx264" + fps = 4 + bitrate = 256 + } + audio { + codec = "libfdk_aac" + bitrate = 256 + sample_rate = 44100 + } + remove_audio = true + tehd_config { + type = "TEHD-100" + } + } +} + +resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { + name = "tf-snapshot" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + width = 128 + height = 128 + resolution_adaptive = false + format = "png" + comment = "test" + fill_type = "white" +} + +resource "tencentcloud_vod_image_sprite_template" "foo" { + sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + sample_interval = 10 + row_count = 3 + column_count = 3 + name = "tf-sprite" + comment = "test" + fill_type = "stretch" + width = 128 + height = 128 + resolution_adaptive = false +} + +resource "tencentcloud_vod_transcode_template" "transcode_template" { + container = "mp4" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + name = "720pTranscodeTemplate" + comment = "test transcode mp4 720p update" + remove_video = 0 + remove_audio = 0 + video_template { + codec = "libx264" + fps = 26 + bitrate = 1000 + resolution_adaptive = "open" + width = 0 + height = 720 + fill_type = "stretch" + vcrf = 1 + gop = 250 + preserve_hdr_switch = "OFF" + codec_tag = "hvc1" + + } + audio_template { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 44100 + audio_channel = 2 + + } + segment_type = "ts" +} + resource "tencentcloud_vod_procedure_template" "foo" { name = "tf-procedure0" comment = "test" sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) media_process_task { adaptive_dynamic_streaming_task_list { - definition = tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id)[1]) } snapshot_by_time_offset_task_list { - definition = tencentcloud_vod_snapshot_by_time_offset_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_snapshot_by_time_offset_template.foo.id)[1]) ext_time_offset_list = [ "3.5s" ] } image_sprite_task_list { - definition = tencentcloud_vod_image_sprite_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_image_sprite_template.foo.id)[1]) + } + transcode_task_list { + definition = tonumber(split("#", tencentcloud_vod_transcode_template.transcode_template.id)[1]) } } } ` -const testAccVodProcedureTemplateUpdate = testAccVodAdaptiveDynamicStreamingTemplate + testAccVodSnapshotByTimeOffsetTemplate + testAccVodImageSpriteTemplate + ` +const testAccVodProcedureTemplateUpdate = ` resource "tencentcloud_vod_sub_application" "sub_application" { - name = "subapplication" + name = "procedure-subapplication" status = "On" description = "this is sub application" } +resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { + format = "HLS" + name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + drm_type = "SimpleAES" + disable_higher_video_bitrate = false + disable_higher_video_resolution = false + comment = "test" + + stream_info { + video { + codec = "libx264" + fps = 3 + bitrate = 128 + } + audio { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 32000 + } + remove_audio = true + } + stream_info { + video { + codec = "libx264" + fps = 4 + bitrate = 256 + } + audio { + codec = "libfdk_aac" + bitrate = 256 + sample_rate = 44100 + } + remove_audio = true + tehd_config { + type = "TEHD-100" + } + } +} + +resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { + name = "tf-snapshot" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + width = 128 + height = 128 + resolution_adaptive = false + format = "png" + comment = "test" + fill_type = "white" +} + +resource "tencentcloud_vod_image_sprite_template" "foo" { + sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + sample_interval = 10 + row_count = 3 + column_count = 3 + name = "tf-sprite" + comment = "test" + fill_type = "stretch" + width = 128 + height = 128 + resolution_adaptive = false +} + +resource "tencentcloud_vod_transcode_template" "transcode_template" { + container = "mp4" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + name = "720pTranscodeTemplate" + comment = "test transcode mp4 720p update" + remove_video = 0 + remove_audio = 0 + video_template { + codec = "libx264" + fps = 26 + bitrate = 1000 + resolution_adaptive = "open" + width = 0 + height = 720 + fill_type = "stretch" + vcrf = 1 + gop = 250 + preserve_hdr_switch = "OFF" + codec_tag = "hvc1" + + } + audio_template { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 44100 + audio_channel = 2 + + } + segment_type = "ts" +} + resource "tencentcloud_vod_procedure_template" "foo" { name = "tf-procedure0" comment = "test-update" sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) media_process_task { adaptive_dynamic_streaming_task_list { - definition = tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id)[1]) } snapshot_by_time_offset_task_list { - definition = tencentcloud_vod_snapshot_by_time_offset_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_snapshot_by_time_offset_template.foo.id)[1]) ext_time_offset_list = [ "3.5s", "4.0s" ] } + transcode_task_list { + definition = tonumber(split("#", tencentcloud_vod_transcode_template.transcode_template.id)[1]) + } } } ` diff --git a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go index 37ba5cae40..a89c836780 100644 --- a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go @@ -178,13 +178,18 @@ func resourceTencentCloudVodSampleSnapshotTemplateRead(d *schema.ResourceData, m service := VodService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + var ( + subAppId int + definition string + ) idSplit := strings.Split(d.Id(), tccommon.FILED_SP) - if len(idSplit) != 2 { - return fmt.Errorf("sample snapshot id is borken, id is %s", d.Id()) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() } - subAppId := idSplit[0] - definition := idSplit[1] - sampleSnapshotTemplate, err := service.DescribeVodSampleSnapshotTemplateById(ctx, helper.StrToUInt64(subAppId), helper.StrToUInt64(definition)) + sampleSnapshotTemplate, err := service.DescribeVodSampleSnapshotTemplateById(ctx, uint64(subAppId), helper.StrToUInt64(definition)) if err != nil { return err } @@ -195,7 +200,9 @@ func resourceTencentCloudVodSampleSnapshotTemplateRead(d *schema.ResourceData, m return nil } - _ = d.Set("sub_app_id", helper.StrToInt(subAppId)) + if subAppId != 0 { + _ = d.Set("sub_app_id", subAppId) + } if sampleSnapshotTemplate.SampleType != nil { _ = d.Set("sample_type", sampleSnapshotTemplate.SampleType) } diff --git a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.md b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.md index 5cbe6d0485..661ef74d64 100644 --- a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.md +++ b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.md @@ -25,7 +25,7 @@ resource "tencentcloud_vod_sample_snapshot_template" "sample_snapshot_template" Import -vod snapshot template can be imported using the id, e.g. +vod snapshot template can be imported using the id($subAppId#$templateId), e.g. ``` terraform import tencentcloud_vod_sample_snapshot_template.sample_snapshot_template $subAppId#$templateId diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go index 233d984d07..fc3b3dc3cd 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" @@ -85,6 +86,13 @@ func ResourceTencentCloudVodSnapshotByTimeOffsetTemplate() *schema.Resource { Computed: true, Description: "Last modified time of template in ISO date format.", }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: "Template type, value range:\n" + + "- Preset: system preset template;\n" + + "- Custom: user-defined templates.", + }, }, } } @@ -107,8 +115,12 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateCreate(d *schema.Resourc if v, ok := d.GetOk("comment"); ok { request.Comment = helper.String(v.(string)) } + var resourceId string if v, ok := d.GetOk("sub_app_id"); ok { - request.SubAppId = helper.IntUint64(v.(int)) + subAppId := v.(int) + resourceId += helper.IntToStr(subAppId) + resourceId += tccommon.FILED_SP + request.SubAppId = helper.IntUint64(subAppId) } request.FillType = helper.String(d.Get("fill_type").(string)) @@ -129,7 +141,8 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateCreate(d *schema.Resourc if response == nil || response.Response == nil { return fmt.Errorf("for vod snapshot by time offset template creation, response is nil") } - d.SetId(strconv.FormatUint(*response.Response.Definition, 10)) + resourceId += strconv.FormatUint(*response.Response.Definition, 10) + d.SetId(resourceId) return resourceTencentCloudVodSnapshotByTimeOffsetTemplateRead(d, meta) } @@ -141,14 +154,21 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateRead(d *schema.ResourceD var ( logId = tccommon.GetLogId(tccommon.ContextNil) ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id = d.Id() - subAppId = d.Get("sub_app_id").(int) + subAppId int + definition string client = meta.(tccommon.ProviderMeta).GetAPIV3Conn() vodService = VodService{client: client} ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + } // waiting for refreshing cache time.Sleep(30 * time.Second) - template, has, err := vodService.DescribeSnapshotByTimeOffsetTemplatesById(ctx, id, subAppId) + template, has, err := vodService.DescribeSnapshotByTimeOffsetTemplatesById(ctx, definition, subAppId) if err != nil { return err } @@ -158,6 +178,7 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateRead(d *schema.ResourceD } _ = d.Set("name", template.Name) + _ = d.Set("type", template.Type) _ = d.Set("width", template.Width) _ = d.Set("height", template.Height) _ = d.Set("resolution_adaptive", *template.ResolutionAdaptive == "open") @@ -166,6 +187,9 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateRead(d *schema.ResourceD _ = d.Set("fill_type", template.FillType) _ = d.Set("create_time", template.CreateTime) _ = d.Set("update_time", template.UpdateTime) + if subAppId != 0 { + _ = d.Set("sub_app_id", subAppId) + } return nil } @@ -176,12 +200,33 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateUpdate(d *schema.Resourc var ( logId = tccommon.GetLogId(tccommon.ContextNil) request = vod.NewModifySnapshotByTimeOffsetTemplateRequest() - id = d.Id() + subAppId int + definition string changeFlag = false ) - idUint, _ := strconv.ParseUint(id, 0, 64) - request.Definition = &idUint + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + request.SubAppId = helper.IntUint64(subAppId) + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + request.SubAppId = helper.IntUint64(v.(int)) + } + } + + request.Definition = helper.StrToUint64Point(definition) + + immutableArgs := []string{"sub_app_id"} + + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) + } + } + if d.HasChange("name") { changeFlag = true request.Name = helper.String(d.Get("name").(string)) @@ -200,10 +245,6 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateUpdate(d *schema.Resourc changeFlag = true request.Comment = helper.String(d.Get("comment").(string)) } - if d.HasChange("sub_app_id") { - changeFlag = true - request.SubAppId = helper.IntUint64(d.Get("sub_app_id").(int)) - } if d.HasChange("fill_type") { changeFlag = true request.FillType = helper.String(d.Get("fill_type").(string)) @@ -236,12 +277,25 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateDelete(d *schema.Resourc logId := tccommon.GetLogId(tccommon.ContextNil) ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id := d.Id() + var ( + subAppId int + definition string + ) + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) + if len(idSplit) == 2 { + subAppId = helper.StrToInt(idSplit[0]) + definition = idSplit[1] + } else { + definition = d.Id() + if v, ok := d.GetOk("sub_app_id"); ok { + subAppId = v.(int) + } + } vodService := VodService{ client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), } - if err := vodService.DeleteSnapshotByTimeOffsetTemplate(ctx, id, uint64(d.Get("sub_app_id").(int))); err != nil { + if err := vodService.DeleteSnapshotByTimeOffsetTemplate(ctx, definition, uint64(subAppId)); err != nil { return err } diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.md b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.md index 8b6dc8d6f5..aac4300751 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.md +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.md @@ -16,8 +16,8 @@ resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { Import -VOD snapshot by time offset template can be imported using the id, e.g. +VOD snapshot by time offset template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_snapshot_by_time_offset_template.foo 46906 +$ terraform import tencentcloud_vod_snapshot_by_time_offset_template.foo $subAppId#$templateId ``` \ No newline at end of file diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go index 9fda33d5b2..210d75def1 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go @@ -4,10 +4,12 @@ import ( "context" "fmt" "strconv" + "strings" "testing" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" svcvod "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/vod" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -74,6 +76,7 @@ func TestAccTencentCloudVodSnapshotByTimeOffsetTemplateResource(t *testing.T) { resource.TestCheckResourceAttr("tencentcloud_vod_snapshot_by_time_offset_template.foo", "fill_type", "white"), resource.TestCheckResourceAttrSet("tencentcloud_vod_snapshot_by_time_offset_template.foo", "create_time"), resource.TestCheckResourceAttrSet("tencentcloud_vod_snapshot_by_time_offset_template.foo", "update_time"), + resource.TestCheckResourceAttrSet("tencentcloud_vod_snapshot_by_time_offset_template.foo", "type"), ), }, { @@ -89,10 +92,9 @@ func TestAccTencentCloudVodSnapshotByTimeOffsetTemplateResource(t *testing.T) { ), }, { - ResourceName: "tencentcloud_vod_snapshot_by_time_offset_template.foo", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"sub_app_id"}, + ResourceName: "tencentcloud_vod_snapshot_by_time_offset_template.foo", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -107,11 +109,13 @@ func testAccCheckVodSnapshotByTimeOffsetTemplateDestroy(s *terraform.State) erro if rs.Type != "tencentcloud_vod_snapshot_by_time_offset_template" { continue } - var ( - filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, - } - ) + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] + filter := map[string]interface{}{ + "definitions": []string{definition}, + "sub_appid": subAppId, + } templates, err := vodService.DescribeSnapshotByTimeOffsetTemplatesByFilter(ctx, filter) if err != nil { @@ -139,11 +143,13 @@ func testAccCheckVodSnapshotByTimeOffsetTemplateExists(n string) resource.TestCh } vodService := svcvod.NewVodService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) - var ( - filter = map[string]interface{}{ - "definitions": []string{rs.Primary.ID}, - } - ) + idSplit := strings.Split(rs.Primary.ID, tccommon.FILED_SP) + subAppId := helper.StrToInt(idSplit[0]) + definition := idSplit[1] + filter := map[string]interface{}{ + "definitions": []string{definition}, + "sub_appid": subAppId, + } templates, err := vodService.DescribeSnapshotByTimeOffsetTemplatesByFilter(ctx, filter) if err != nil { return err @@ -156,8 +162,15 @@ func testAccCheckVodSnapshotByTimeOffsetTemplateExists(n string) resource.TestCh } const testAccVodSnapshotByTimeOffsetTemplate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "sbtot-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { name = "tf-snapshot" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) width = 128 height = 128 resolution_adaptive = false @@ -168,8 +181,15 @@ resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { ` const testAccVodSnapshotByTimeOffsetTemplateUpdate = ` +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "image-sprite-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { name = "tf-snapshot-update" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) width = 129 height = 129 resolution_adaptive = true diff --git a/tencentcloud/services/vod/service_tencentcloud_vod.go b/tencentcloud/services/vod/service_tencentcloud_vod.go index 2a1ad15ceb..781176db4d 100644 --- a/tencentcloud/services/vod/service_tencentcloud_vod.go +++ b/tencentcloud/services/vod/service_tencentcloud_vod.go @@ -75,10 +75,13 @@ func (me *VodService) DescribeAdaptiveDynamicStreamingTemplatesById(ctx context. var ( filter = map[string]interface{}{ "definitions": []string{templateId}, - "sub_appid": subAppId, } ) + if subAppId != 0 { + filter["sub_appid"] = subAppId + } + templates, errRet := me.DescribeAdaptiveDynamicStreamingTemplatesByFilter(ctx, filter) if errRet != nil { return @@ -369,10 +372,12 @@ func (me *VodService) DescribeImageSpriteTemplatesById(ctx context.Context, temp var ( filter = map[string]interface{}{ "definitions": []string{templateId}, - "sub_appid": subAppId, } ) + if subAppId != 0 { + filter["sub_appid"] = subAppId + } templates, errRet := me.DescribeImageSpriteTemplatesByFilter(ctx, filter) if errRet != nil { return @@ -515,7 +520,9 @@ func (me *VodService) DescribeVodSampleSnapshotTemplateById(ctx context.Context, logId := tccommon.GetLogId(ctx) request := vod.NewDescribeSampleSnapshotTemplatesRequest() - request.SubAppId = helper.Uint64(subAppId) + if subAppId != 0 { + request.SubAppId = helper.Uint64(subAppId) + } request.Definitions = []*uint64{helper.Uint64(definition)} defer func() { From 2ab559a2fde45f929793aee5977879cc3b4fa9f2 Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 17:20:28 +0800 Subject: [PATCH 2/9] add changelog && update doc --- .changelog/2569.txt | 19 +++ ...e_dynamic_streaming_template.html.markdown | 63 ++++++---- .../r/vod_image_sprite_template.html.markdown | 19 ++- .../r/vod_procedure_template.html.markdown | 115 ++++++++++++++---- ...vod_sample_snapshot_template.html.markdown | 2 +- ...shot_by_time_offset_template.html.markdown | 7 +- 6 files changed, 175 insertions(+), 50 deletions(-) create mode 100644 .changelog/2569.txt diff --git a/.changelog/2569.txt b/.changelog/2569.txt new file mode 100644 index 0000000000..7a9fd6ceba --- /dev/null +++ b/.changelog/2569.txt @@ -0,0 +1,19 @@ +```release-note:enhancement +resource/tencentcloud_vod_adaptive_dynamic_streaming_template: support params vcrf, gop, preserve_hdr_switch, codec_tag; compatible id +``` + +```release-note:enhancement +resource/tencentcloud_vod_image_sprite_template: support params format, type; compatible id +``` + +```release-note:enhancement +resource/tencentcloud_vod_procedure_template: update params media_process_task, support params ai_analysis_task, ai_recognition_task, review_audio_video_task, type; compatible id +``` + +```release-note:enhancement +resource/tencentcloud_vod_sample_snapshot_template: compatible id. +``` + +```release-note:enhancement +resource/tencentcloud_vod_snapshot_by_time_offset_template: support params type; compatible id +``` diff --git a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown index 55fefeba0e..156ab1e7db 100644 --- a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown +++ b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown @@ -14,44 +14,36 @@ Provide a resource to create a VOD adaptive dynamic streaming template. ## Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "adaptive-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = false disable_higher_video_resolution = false comment = "test" - stream_info { - video { - codec = "libx265" - fps = 4 - bitrate = 129 - resolution_adaptive = false - width = 128 - height = 128 - fill_type = "stretch" - } - audio { - codec = "libmp3lame" - bitrate = 129 - sample_rate = 44100 - audio_channel = "dual" - } - remove_audio = false - } stream_info { video { codec = "libx264" - fps = 4 - bitrate = 256 + fps = 3 + bitrate = 128 } audio { codec = "libfdk_aac" - bitrate = 256 - sample_rate = 44100 + bitrate = 128 + sample_rate = 32000 } remove_audio = true + tehd_config { + type = "TEHD-100" + } } } ``` @@ -81,15 +73,38 @@ The `stream_info` object supports the following: * `audio` - (Required, List) Audio parameter information. * `video` - (Required, List) Video parameter information. * `remove_audio` - (Optional, Bool) Whether to remove audio stream. Valid values: `false`: no, `true`: yes. `false` by default. +* `remove_video` - (Optional, Bool) Whether to remove video stream. Valid values: `false`: no, `true`: yes. `false` by default. +* `tehd_config` - (Optional, List) Extremely fast HD transcoding parameters. + +The `tehd_config` object of `stream_info` supports the following: + +* `type` - (Required, String) Extreme high-speed HD type, available values: +- TEHD-100: super high definition-100th; +- OFF: turn off Ultra High definition. +* `max_video_bitrate` - (Optional, Int) Video bitrate limit, which is valid when Type specifies extreme speed HD type. If you leave it empty or enter 0, there is no video bitrate limit. The `video` object of `stream_info` supports the following: * `bitrate` - (Required, Int) Bitrate of video stream in Kbps. Value range: `0` and `[128, 35000]`. If the value is `0`, the bitrate of the video will be the same as that of the source video. * `codec` - (Required, String) Video stream encoder. Valid values: `libx264`,`libx265`,`av1`. `libx264`: H.264, `libx265`: H.265, `av1`: AOMedia Video 1. Currently, a resolution within 640x480 must be specified for `H.265`. and the `av1` container only supports mp4. * `fps` - (Required, Int) Video frame rate in Hz. Value range: `[0, 60]`. If the value is `0`, the frame rate will be the same as that of the source video. +* `codec_tag` - (Optional, String) Encoding label, valid only if the encoding format of the video stream is H.265 encoding. Available values: +- hvc1: stands for hvc1 tag; +- hev1: stands for the hev1 tag; +Default value: hvc1. * `fill_type` - (Optional, String) Fill type. Fill refers to the way of processing a screenshot when its aspect ratio is different from that of the source video. The following fill types are supported: `stretch`: stretch. The screenshot will be stretched frame by frame to match the aspect ratio of the source video, which may make the screenshot shorter or longer; `black`: fill with black. This option retains the aspect ratio of the source video for the screenshot and fills the unmatched area with black color blocks. Default value: black. Note: this field may return null, indicating that no valid values can be obtained. +* `gop` - (Optional, Int) Interval between Keyframe I frames, value range: 0 and [1, 100000], unit: number of frames. When you fill in 0 or leave it empty, the gop length is automatically set. * `height` - (Optional, Int) Maximum value of the height (or short side) of a video stream in px. Value range: `0` and `[128, 4096]`. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, `width` will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. Note: this field may return null, indicating that no valid values can be obtained. +* `preserve_hdr_switch` - (Optional, String) Whether the transcoding output still maintains HDR when the original video is HDR (High Dynamic Range). Value range: +- ON: if the original file is HDR, the transcoding output remains HDR;, otherwise the transcoding output is SDR (Standard Dynamic Range); +- OFF: regardless of whether the original file is HDR or SDR, the transcoding output is SDR; +Default value: OFF. * `resolution_adaptive` - (Optional, Bool) Resolution adaption. Valid values: `true`,`false`. `true`: enabled. In this case, `width` represents the long side of a video, while `height` the short side; `false`: disabled. In this case, `width` represents the width of a video, while `height` the height. Default value: `true`. Note: this field may return null, indicating that no valid values can be obtained. +* `vcrf` - (Optional, Int) Video constant bit rate control factor, value range is [1,51]. +Note: +- If this parameter is specified, the bitrate control method of CRF will be used for transcoding (the video bitrate will no longer take effect); +- This field is required when the video stream encoding format is H.266. The recommended value is 28; +- If there are no special requirements, it is not recommended to specify this parameter. * `width` - (Optional, Int) Maximum value of the width (or long side) of a video stream in px. Value range: `0` and `[128, 4096]`. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, `width` will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. Note: this field may return null, indicating that no valid values can be obtained. ## Attributes Reference @@ -103,9 +118,9 @@ In addition to all arguments above, the following attributes are exported: ## Import -VOD adaptive dynamic streaming template can be imported using the id, e.g. +VOD adaptive dynamic streaming template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_adaptive_dynamic_streaming_template.foo 169141 +$ terraform import tencentcloud_vod_adaptive_dynamic_streaming_template.foo $subAppId#$templateId ``` diff --git a/website/docs/r/vod_image_sprite_template.html.markdown b/website/docs/r/vod_image_sprite_template.html.markdown index 9c4244100b..271c77a9fd 100644 --- a/website/docs/r/vod_image_sprite_template.html.markdown +++ b/website/docs/r/vod_image_sprite_template.html.markdown @@ -14,8 +14,15 @@ Provide a resource to create a VOD image sprite template. ## Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "image-sprite-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 10 row_count = 3 column_count = 3 @@ -39,6 +46,11 @@ The following arguments are supported: * `sample_type` - (Required, String) Sampling type. Valid values: `Percent`, `Time`. `Percent`: by percent. `Time`: by time interval. * `comment` - (Optional, String) Template description. Length limit: 256 characters. * `fill_type` - (Optional, String) Fill refers to the way of processing a screenshot when its aspect ratio is different from that of the source video. The following fill types are supported: `stretch`: stretch. The screenshot will be stretched frame by frame to match the aspect ratio of the source video, which may make the screenshot shorter or longer; `black`: fill with black. This option retains the aspect ratio of the source video for the screenshot and fills the unmatched area with black color blocks. Default value: `black`. +* `format` - (Optional, String) Image format, Valid values: +- jpg: jpg format; +- png: png format; +- webp: webp format; +Default value: jpg. * `height` - (Optional, Int) Maximum value of the `height` (or short side) of a screenshot in px. Value range: 0 and [128, 4,096]. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, `width` will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. * `resolution_adaptive` - (Optional, Bool) Resolution adaption. Valid values: `true`,`false`. `true`: enabled. In this case, `width` represents the long side of a video, while `height` the short side; `false`: disabled. In this case, `width` represents the width of a video, while `height` the height. Default value: `true`. * `sub_app_id` - (Optional, Int) Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty. @@ -50,14 +62,17 @@ In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. * `create_time` - Creation time of template in ISO date format. +* `type` - Template type, value range: +- Preset: system preset template; +- Custom: user-defined templates. * `update_time` - Last modified time of template in ISO date format. ## Import -VOD image sprite template can be imported using the id, e.g. +VOD image sprite template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_image_sprite_template.foo 51156 +$ terraform import tencentcloud_vod_image_sprite_template.foo $subAppId#$templateId ``` diff --git a/website/docs/r/vod_procedure_template.html.markdown b/website/docs/r/vod_procedure_template.html.markdown index e5d885f57f..42f1fad29f 100644 --- a/website/docs/r/vod_procedure_template.html.markdown +++ b/website/docs/r/vod_procedure_template.html.markdown @@ -14,9 +14,16 @@ Provide a resource to create a VOD procedure template. ## Example Usage ```hcl +resource "tencentcloud_vod_sub_application" "sub_application" { + name = "procedure-subapplication" + status = "On" + description = "this is sub application" +} + resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { format = "HLS" name = "tf-adaptive" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) drm_type = "SimpleAES" disable_higher_video_bitrate = false disable_higher_video_resolution = false @@ -24,21 +31,16 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { stream_info { video { - codec = "libx265" - fps = 4 - bitrate = 129 - resolution_adaptive = false - width = 128 - height = 128 - fill_type = "stretch" + codec = "libx264" + fps = 3 + bitrate = 128 } audio { - codec = "libmp3lame" - bitrate = 129 - sample_rate = 44100 - audio_channel = "dual" + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 32000 } - remove_audio = false + remove_audio = true } stream_info { video { @@ -52,12 +54,16 @@ resource "tencentcloud_vod_adaptive_dynamic_streaming_template" "foo" { sample_rate = 44100 } remove_audio = true + tehd_config { + type = "TEHD-100" + } } } resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { name = "tf-snapshot" - width = 130 + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + width = 128 height = 128 resolution_adaptive = false format = "png" @@ -67,6 +73,7 @@ resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { resource "tencentcloud_vod_image_sprite_template" "foo" { sample_type = "Percent" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) sample_interval = 10 row_count = 3 column_count = 3 @@ -78,28 +85,56 @@ resource "tencentcloud_vod_image_sprite_template" "foo" { resolution_adaptive = false } -resource "tencentcloud_vod_sub_application" "sub_application" { - name = "subapplication" - status = "On" - description = "this is sub application" +resource "tencentcloud_vod_transcode_template" "transcode_template" { + container = "mp4" + sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) + name = "720pTranscodeTemplate" + comment = "test transcode mp4 720p update" + remove_video = 0 + remove_audio = 0 + video_template { + codec = "libx264" + fps = 26 + bitrate = 1000 + resolution_adaptive = "open" + width = 0 + height = 720 + fill_type = "stretch" + vcrf = 1 + gop = 250 + preserve_hdr_switch = "OFF" + codec_tag = "hvc1" + + } + audio_template { + codec = "libfdk_aac" + bitrate = 128 + sample_rate = 44100 + audio_channel = 2 + + } + segment_type = "ts" } resource "tencentcloud_vod_procedure_template" "foo" { - name = "tf-procedure" + name = "tf-procedure0" comment = "test" sub_app_id = tonumber(split("#", tencentcloud_vod_sub_application.sub_application.id)[1]) media_process_task { adaptive_dynamic_streaming_task_list { - definition = tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_adaptive_dynamic_streaming_template.foo.id)[1]) } snapshot_by_time_offset_task_list { - definition = tencentcloud_vod_snapshot_by_time_offset_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_snapshot_by_time_offset_template.foo.id)[1]) ext_time_offset_list = [ "3.5s" ] } image_sprite_task_list { - definition = tencentcloud_vod_image_sprite_template.foo.id + definition = tonumber(split("#", tencentcloud_vod_image_sprite_template.foo.id)[1]) + } + transcode_task_list { + definition = tonumber(split("#", tencentcloud_vod_transcode_template.transcode_template.id)[1]) } } } @@ -110,8 +145,11 @@ resource "tencentcloud_vod_procedure_template" "foo" { The following arguments are supported: * `name` - (Required, String, ForceNew) Task flow name (up to 20 characters). +* `ai_analysis_task` - (Optional, List) Parameter of AI-based content analysis task. +* `ai_recognition_task` - (Optional, List) Type parameter of AI-based content recognition task. * `comment` - (Optional, String) Template description. Length limit: 256 characters. * `media_process_task` - (Optional, List) Parameter of video processing task. +* `review_audio_video_task` - (Optional, List) Type parameter of AI-based content recognition task. * `sub_app_id` - (Optional, Int) Subapplication ID in VOD. For customers who activate VOD from December 25, 2023, if they access the resources in the VOD application (whether it is the default application or the newly created application), you must fill in this field as Application ID. The `adaptive_dynamic_streaming_task_list` object of `media_process_task` supports the following: @@ -119,12 +157,24 @@ The `adaptive_dynamic_streaming_task_list` object of `media_process_task` suppor * `definition` - (Required, String) Adaptive bitrate streaming template ID. * `watermark_list` - (Optional, List) List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained. +The `ai_analysis_task` object supports the following: + +* `definition` - (Optional, String) Video content analysis template ID. + +The `ai_recognition_task` object supports the following: + +* `definition` - (Optional, String) Intelligent video recognition template ID. + The `animated_graphic_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Animated image generating template ID. * `end_time_offset` - (Required, Float64) End time of animated image in video in seconds. * `start_time_offset` - (Required, Float64) Start time of animated image in video in seconds. +The `copy_right_watermark` object of `transcode_task_list` supports the following: + +* `text` - (Optional, String) Copyright information, maximum length is 200 characters. + The `cover_by_snapshot_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Time point screen capturing template ID. @@ -132,6 +182,10 @@ The `cover_by_snapshot_task_list` object of `media_process_task` supports the fo * `position_value` - (Required, Float64) Screenshot position: For time point screen capturing, this means to take a screenshot at a specified time point (in seconds) and use it as the cover. For percentage screen capturing, this value means to take a screenshot at a specified percentage of the video duration and use it as the cover. * `watermark_list` - (Optional, List) List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained. +The `head_tail_list` object of `transcode_task_list` supports the following: + +* `definition` - (Optional, String) Video opening/closing credits configuration template ID. + The `image_sprite_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Image sprite generating template ID. @@ -156,6 +210,12 @@ The `mosaic_list` object of `transcode_task_list` supports the following: * `x_pos` - (Optional, String) The horizontal position of the origin of the blur relative to the origin of coordinates of the video. `%` and `px` formats are supported: If the string ends in `%`, the XPos of the blur will be the specified percentage of the video width; for example, 10% means that XPos is 10% of the video width; If the string ends in `px`, the XPos of the blur will be the specified px; for example, 100px means that XPos is 100 px. Default value: `0px`. * `y_pos` - (Optional, String) Vertical position of the origin of blur relative to the origin of coordinates of video. `%` and `px` formats are supported: If the string ends in `%`, the YPos of the blur will be the specified percentage of the video height; for example, 10% means that YPos is 10% of the video height; If the string ends in `px`, the YPos of the blur will be the specified px; for example, 100px means that YPos is 100 px. Default value: `0px`. +The `review_audio_video_task` object supports the following: + +* `review_contents` - (Optional, List) The type of moderated content. Valid values: +- `Media`: The original audio/video; +- `Cover`: Thumbnails. + The `sample_snapshot_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Sampled screen capturing template ID. @@ -165,12 +225,22 @@ The `snapshot_by_time_offset_task_list` object of `media_process_task` supports * `definition` - (Required, String) Time point screen capturing template ID. * `ext_time_offset_list` - (Optional, List) The list of screenshot time points. `s` and `%` formats are supported: When a time point string ends with `s`, its unit is second. For example, `3.5s` means the 3.5th second of the video; When a time point string ends with `%`, it is marked with corresponding percentage of the video duration. For example, `10%` means that the time point is at the 10% of the video entire duration. +* `time_offset_list` - (Optional, List) List of time points for screencapturing in milliseconds. Note: this field may return null, indicating that no valid values can be obtained. * `watermark_list` - (Optional, List) List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained. +The `trace_watermark` object of `transcode_task_list` supports the following: + +* `switch` - (Optional, String) Whether to use digital watermarks. This parameter is required. Valid values: ON, OFF. + The `transcode_task_list` object of `media_process_task` supports the following: * `definition` - (Required, String) Video transcoding template ID. +* `copy_right_watermark` - (Optional, List) opyright watermark. +* `end_time_offset` - (Optional, Float64) End time offset of blur in seconds. If this parameter is left empty or `0` is entered, the blur will exist till the last video frame; If this value is greater than `0` (e.g., n), the blur will exist till second n; If this value is smaller than `0` (e.g., -n), the blur will exist till second n before the last video frame. +* `head_tail_list` - (Optional, List) List of video opening/closing credits configuration template IDs. You can enter up to 10 IDs. * `mosaic_list` - (Optional, List) List of blurs. Up to 10 ones can be supported. +* `start_time_offset` - (Optional, Float64) Start time offset of blur in seconds. If this parameter is left empty or `0` is entered, the blur will appear upon the first video frame. If this parameter is left empty or `0` is entered, the blur will appear upon the first video frame; If this value is greater than `0` (e.g., n), the blur will appear at second n after the first video frame; If this value is smaller than `0` (e.g., -n), the blur will appear at second n before the last video frame. +* `trace_watermark` - (Optional, List) Digital watermark. * `watermark_list` - (Optional, List) List of up to `10` image or text watermarks. Note: this field may return null, indicating that no valid values can be obtained. The `watermark_list` object of `adaptive_dynamic_streaming_task_list` supports the following: @@ -219,6 +289,9 @@ In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. * `create_time` - Creation time of template in ISO date format. +* `type` - Template type, value range: +- Preset: system preset template; +- Custom: user-defined templates. * `update_time` - Last modified time of template in ISO date format. diff --git a/website/docs/r/vod_sample_snapshot_template.html.markdown b/website/docs/r/vod_sample_snapshot_template.html.markdown index e4a9b6833c..ed66435aba 100644 --- a/website/docs/r/vod_sample_snapshot_template.html.markdown +++ b/website/docs/r/vod_sample_snapshot_template.html.markdown @@ -59,7 +59,7 @@ In addition to all arguments above, the following attributes are exported: ## Import -vod snapshot template can be imported using the id, e.g. +vod snapshot template can be imported using the id($subAppId#$templateId), e.g. ``` terraform import tencentcloud_vod_sample_snapshot_template.sample_snapshot_template $subAppId#$templateId diff --git a/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown b/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown index 2613d659c0..5eb5ca4a15 100644 --- a/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown +++ b/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown @@ -44,14 +44,17 @@ In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. * `create_time` - Creation time of template in ISO date format. +* `type` - Template type, value range: +- Preset: system preset template; +- Custom: user-defined templates. * `update_time` - Last modified time of template in ISO date format. ## Import -VOD snapshot by time offset template can be imported using the id, e.g. +VOD snapshot by time offset template can be imported using the id($subAppId#$templateId), e.g. ``` -$ terraform import tencentcloud_vod_snapshot_by_time_offset_template.foo 46906 +$ terraform import tencentcloud_vod_snapshot_by_time_offset_template.foo $subAppId#$templateId ``` From 1ed3a86e3e343166ba0a1e400842ad2e23eb5d4d Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 17:37:20 +0800 Subject: [PATCH 3/9] update --- .../resource_tc_vod_snapshot_by_time_offset_template.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go index fc3b3dc3cd..1c2367bda3 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" vod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" @@ -130,8 +131,13 @@ func resourceTencentCloudVodSnapshotByTimeOffsetTemplateCreate(d *schema.Resourc ratelimit.Check(request.GetAction()) response, err = meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVodClient().CreateSnapshotByTimeOffsetTemplate(request) if err != nil { + if sdkError, ok := err.(*sdkErrors.TencentCloudSDKError); ok { + if sdkError.Code == "FailedOperation" && sdkError.Message == "invalid vod user" { + return resource.RetryableError(err) + } + } log.Printf("[CRITAL]%s api[%s] fail, reason:%s", logId, request.GetAction(), err.Error()) - return tccommon.RetryError(err) + return resource.NonRetryableError(err) } return nil }) From dc2c58cfa5a370abfc63738a63561f19da488cda Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 17:51:25 +0800 Subject: [PATCH 4/9] update --- .../services/vod/resource_tc_vod_image_sprite_template.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go index c040520e37..b1b77ebc3a 100644 --- a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" vod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" @@ -160,8 +161,13 @@ func resourceTencentCloudVodImageSpriteTemplateCreate(d *schema.ResourceData, me ratelimit.Check(request.GetAction()) response, err = meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVodClient().CreateImageSpriteTemplate(request) if err != nil { + if sdkError, ok := err.(*sdkErrors.TencentCloudSDKError); ok { + if sdkError.Code == "FailedOperation" && sdkError.Message == "invalid vod user" { + return resource.RetryableError(err) + } + } log.Printf("[CRITAL]%s api[%s] fail, reason:%s", logId, request.GetAction(), err.Error()) - return tccommon.RetryError(err) + return resource.NonRetryableError(err) } return nil }) From c36c176be141876fa9b41773d62a5c6d4977cedc Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 18:48:58 +0800 Subject: [PATCH 5/9] update --- .../services/vod/resource_tc_vod_procedure_template_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go index 744399529d..282b7340bf 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template_test.go @@ -48,14 +48,12 @@ func init() { func TestAccTencentCloudVodProcedureTemplateResource(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - PreCheck: func() { tcacctest.AccPreCheck(t) }, - Providers: tcacctest.AccProviders, - CheckDestroy: testAccCheckVodProcedureTemplateDestroy, + PreCheck: func() { tcacctest.AccPreCheck(t) }, + Providers: tcacctest.AccProviders, Steps: []resource.TestStep{ { Config: testAccVodProcedureTemplate, Check: resource.ComposeTestCheckFunc( - testAccCheckVodProcedureTemplateExists("tencentcloud_vod_procedure_template.foo"), resource.TestCheckResourceAttr("tencentcloud_vod_procedure_template.foo", "name", "tf-procedure0"), resource.TestCheckResourceAttr("tencentcloud_vod_procedure_template.foo", "comment", "test"), resource.TestCheckResourceAttr("tencentcloud_vod_procedure_template.foo", "media_process_task.#", "1"), From 374aceb21574a2762be42d2f664e11716b14f74f Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 19:09:32 +0800 Subject: [PATCH 6/9] update review_audio_video_task --- tencentcloud/services/vod/resource_tc_vod_procedure_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go index 2517e8d1e6..f87d13c1bf 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go @@ -1111,7 +1111,7 @@ func resourceTencentCloudVodProcedureTemplateRead(d *schema.ResourceData, meta i for _, revireviewContent := range template.ReviewAudioVideoTask.ReviewContents { reviewContentList = append(reviewContentList, *revireviewContent) } - + reviewAudioVideoTask["review_contents"] = reviewContentList } } _ = d.Set("review_audio_video_task", []interface{}{reviewAudioVideoTask}) From 3731c0c6b7f162db73ee490b6f14340e396562ae Mon Sep 17 00:00:00 2001 From: mikatong Date: Fri, 22 Mar 2024 19:52:54 +0800 Subject: [PATCH 7/9] update --- .../resource_tc_vod_snapshot_by_time_offset_template_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go index 210d75def1..e70bce0f54 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template_test.go @@ -182,7 +182,7 @@ resource "tencentcloud_vod_snapshot_by_time_offset_template" "foo" { const testAccVodSnapshotByTimeOffsetTemplateUpdate = ` resource "tencentcloud_vod_sub_application" "sub_application" { - name = "image-sprite-subapplication" + name = "sbtot-subapplication" status = "On" description = "this is sub application" } From 7088554dd7312bb43e1dff45f8beafe1ba085dd9 Mon Sep 17 00:00:00 2001 From: mikatong Date: Mon, 25 Mar 2024 16:10:13 +0800 Subject: [PATCH 8/9] update --- .changelog/2569.txt | 10 +-- ...vod_adaptive_dynamic_streaming_template.go | 85 +++++++++++++------ .../resource_tc_vod_image_sprite_template.go | 4 +- .../vod/resource_tc_vod_procedure_template.go | 2 +- ...tc_vod_snapshot_by_time_offset_template.go | 2 +- ...e_dynamic_streaming_template.html.markdown | 2 +- .../r/vod_image_sprite_template.html.markdown | 2 +- .../r/vod_procedure_template.html.markdown | 2 +- ...shot_by_time_offset_template.html.markdown | 2 +- 9 files changed, 73 insertions(+), 38 deletions(-) diff --git a/.changelog/2569.txt b/.changelog/2569.txt index 7a9fd6ceba..b23a2947c4 100644 --- a/.changelog/2569.txt +++ b/.changelog/2569.txt @@ -1,19 +1,19 @@ ```release-note:enhancement -resource/tencentcloud_vod_adaptive_dynamic_streaming_template: support params vcrf, gop, preserve_hdr_switch, codec_tag; compatible id +resource/tencentcloud_vod_adaptive_dynamic_streaming_template: Add vcrf, gop, preserve_hdr_switch, codec_tag. Adjust resource unique id to subAppId#templateId. ``` ```release-note:enhancement -resource/tencentcloud_vod_image_sprite_template: support params format, type; compatible id +resource/tencentcloud_vod_image_sprite_template: Add format, type. Adjust resource unique id to subAppId#templateId. ``` ```release-note:enhancement -resource/tencentcloud_vod_procedure_template: update params media_process_task, support params ai_analysis_task, ai_recognition_task, review_audio_video_task, type; compatible id +resource/tencentcloud_vod_procedure_template: Update params media_process_task, add ai_analysis_task, ai_recognition_task, review_audio_video_task, type. Adjust resource unique id to subAppId#templateId. ``` ```release-note:enhancement -resource/tencentcloud_vod_sample_snapshot_template: compatible id. +resource/tencentcloud_vod_sample_snapshot_template: Adjust resource unique id to subAppId#templateId. ``` ```release-note:enhancement -resource/tencentcloud_vod_snapshot_by_time_offset_template: support params type; compatible id +resource/tencentcloud_vod_snapshot_by_time_offset_template: Add type. Adjust resource unique id to subAppId#templateId. ``` diff --git a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go index cd72ac8cf2..4bb304400a 100644 --- a/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_adaptive_dynamic_streaming_template.go @@ -68,7 +68,7 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource "sub_app_id": { Type: schema.TypeInt, Optional: true, - Description: "Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty.", + Description: "The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID.", }, "stream_info": { Type: schema.TypeList, @@ -144,7 +144,7 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource "preserve_hdr_switch": { Type: schema.TypeString, Optional: true, - Default: "OFF", + Computed: true, Description: "Whether the transcoding output still maintains HDR when the original video is HDR (High Dynamic Range). Value range:\n" + "- ON: if the original file is HDR, the transcoding output remains HDR;, otherwise the transcoding output is SDR (Standard Dynamic Range);\n" + "- OFF: regardless of whether the original file is HDR or SDR, the transcoding output is SDR;\n" + @@ -153,7 +153,7 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource "codec_tag": { Type: schema.TypeString, Optional: true, - Default: "hvc1", + Computed: true, Description: "Encoding label, valid only if the encoding format of the video stream is H.265 encoding. Available values:\n" + "- hvc1: stands for hvc1 tag;\n" + "- hev1: stands for the hev1 tag;\n" + @@ -203,7 +203,7 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource "remove_video": { Type: schema.TypeBool, Optional: true, - Default: false, + Computed: true, Description: "Whether to remove video stream. Valid values: `false`: no, `true`: yes. `false` by default.", }, "tehd_config": { @@ -225,7 +225,7 @@ func ResourceTencentCloudVodAdaptiveDynamicStreamingTemplate() *schema.Resource "max_video_bitrate": { Type: schema.TypeInt, Optional: true, - Default: 0, + Computed: true, Description: "Video bitrate limit, which is valid when Type specifies extreme speed HD type. If you leave it empty or enter 0, there is no video bitrate limit.", }, }, @@ -276,12 +276,11 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res } streamInfos := d.Get("stream_info").([]interface{}) request.StreamInfos = make([]*vod.AdaptiveStreamTemplate, 0, len(streamInfos)) - for idx, item := range streamInfos { + for _, item := range streamInfos { v := item.(map[string]interface{}) video := v["video"].([]interface{})[0].(map[string]interface{}) audio := v["audio"].([]interface{})[0].(map[string]interface{}) rAudio := REMOVE_AUDIO_TO_UNINT[v["remove_audio"].(bool)] - rVideo := REMOVE_AUDIO_TO_UNINT[v["remove_video"].(bool)] videoTemplateInfo := &vod.VideoTemplateInfo{ Codec: helper.String(video["codec"].(string)), Fps: helper.IntUint64(video["fps"].(int)), @@ -290,17 +289,24 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res Width: helper.IntUint64(video["width"].(int)), Height: helper.IntUint64(video["height"].(int)), FillType: helper.String(video["fill_type"].(string)), - Vcrf: helper.IntUint64(video["vcrf"].(int)), - Gop: helper.IntUint64(video["gop"].(int)), - PreserveHDRSwitch: helper.String(video["preserve_hdr_switch"].(string)), - CodecTag: helper.String(video["codec_tag"].(string)), } - if v, ok := d.GetOkExists(fmt.Sprintf("stream_info.%d.vcrf", idx)); ok { + var rVideo uint64 + if v, ok := video["remove_video"]; ok && v.(bool) { + rVideo = REMOVE_AUDIO_TO_UNINT[v.(bool)] + } + if v, ok := video["vcrf"]; ok && v.(int) != 0 { videoTemplateInfo.Vcrf = helper.IntUint64(v.(int)) } - if v, ok := d.GetOkExists(fmt.Sprintf("stream_info.%d.gop", idx)); ok { + if v, ok := video["gop"]; ok { videoTemplateInfo.Gop = helper.IntUint64(v.(int)) } + if v, ok := video["preserve_hdr_switch"]; ok && v.(string) != "" { + videoTemplateInfo.PreserveHDRSwitch = helper.String(v.(string)) + } + if v, ok := video["codec_tag"]; ok && v.(string) != "" { + videoTemplateInfo.CodecTag = helper.String(v.(string)) + } + var tehdConfig map[string]interface{} if len(v["tehd_config"].([]interface{})) > 0 { tehdConfig = v["tehd_config"].([]interface{})[0].(map[string]interface{}) @@ -320,10 +326,13 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateCreate(d *schema.Res if tehdConfig == nil { return nil } - return &vod.TEHDConfig{ - Type: helper.String(tehdConfig["type"].(string)), - MaxVideoBitrate: helper.IntUint64(tehdConfig["max_video_bitrate"].(int)), + tehd := &vod.TEHDConfig{ + Type: helper.String(tehdConfig["type"].(string)), + } + if v, ok := tehdConfig["max_video_bitrate"]; ok { + tehd.MaxVideoBitrate = helper.IntUint64(v.(int)) } + return tehd }(), }) } @@ -510,7 +519,10 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res tehdConfig = v["tehd_config"].([]interface{})[0].(map[string]interface{}) } rAudio := REMOVE_AUDIO_TO_UNINT[v["remove_audio"].(bool)] - rVideo := REMOVE_AUDIO_TO_UNINT[v["remove_video"].(bool)] + var rVideo uint64 + if v, ok := video["remove_video"]; ok && v.(bool) { + rVideo = REMOVE_AUDIO_TO_UNINT[v.(bool)] + } request.StreamInfos = append(request.StreamInfos, &vod.AdaptiveStreamTemplate{ Video: &vod.VideoTemplateInfo{ Codec: helper.String(video["codec"].(string)), @@ -529,11 +541,31 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res } return helper.IntUint64(height) }(video["height"].(int)), - FillType: helper.String(video["fill_type"].(string)), - Vcrf: helper.IntUint64(video["vcrf"].(int)), - Gop: helper.IntUint64(video["gop"].(int)), - PreserveHDRSwitch: helper.String(video["preserve_hdr_switch"].(string)), - CodecTag: helper.String(video["codec_tag"].(string)), + FillType: helper.String(video["fill_type"].(string)), + Vcrf: func() *uint64 { + if v, ok := video["vcrf"]; !ok || v.(int) == 0 { + return nil + } + return helper.IntUint64(video["vcrf"].(int)) + }(), + Gop: func() *uint64 { + if _, ok := video["gop"]; !ok { + return nil + } + return helper.IntUint64(video["gop"].(int)) + }(), + PreserveHDRSwitch: func() *string { + if v, ok := video["preserve_hdr_switch"]; !ok || v.(string) == "" { + return nil + } + return helper.String(video["preserve_hdr_switch"].(string)) + }(), + CodecTag: func() *string { + if v, ok := video["codec_tag"]; !ok || v.(string) == "" { + return nil + } + return helper.String(video["codec_tag"].(string)) + }(), }, Audio: &vod.AudioTemplateInfo{ Codec: helper.String(audio["codec"].(string)), @@ -547,10 +579,13 @@ func resourceTencentCloudVodAdaptiveDynamicStreamingTemplateUpdate(d *schema.Res if tehdConfig == nil { return nil } - return &vod.TEHDConfig{ - Type: helper.String(tehdConfig["type"].(string)), - MaxVideoBitrate: helper.IntUint64(tehdConfig["max_video_bitrate"].(int)), + tehd := &vod.TEHDConfig{ + Type: helper.String(tehdConfig["type"].(string)), + } + if v, ok := tehdConfig["max_video_bitrate"]; ok { + tehd.MaxVideoBitrate = helper.IntUint64(v.(int)) } + return tehd }(), }) } diff --git a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go index b1b77ebc3a..82c44a5143 100644 --- a/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_image_sprite_template.go @@ -90,12 +90,12 @@ func ResourceTencentCloudVodImageSpriteTemplate() *schema.Resource { "sub_app_id": { Type: schema.TypeInt, Optional: true, - Description: "Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty.", + Description: "The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID.", }, "format": { Type: schema.TypeString, Optional: true, - Default: "jpg", + Computed: true, Description: "Image format, Valid values:\n" + "- jpg: jpg format;\n" + "- png: png format;\n" + diff --git a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go index f87d13c1bf..b0e8aaa928 100644 --- a/tencentcloud/services/vod/resource_tc_vod_procedure_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_procedure_template.go @@ -44,7 +44,7 @@ func ResourceTencentCloudVodProcedureTemplate() *schema.Resource { "sub_app_id": { Type: schema.TypeInt, Optional: true, - Description: "Subapplication ID in VOD. For customers who activate VOD from December 25, 2023, if they access the resources in the VOD application (whether it is the default application or the newly created application), you must fill in this field as Application ID.", + Description: "The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID.", }, "media_process_task": { Type: schema.TypeList, diff --git a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go index 1c2367bda3..1824bad154 100644 --- a/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_snapshot_by_time_offset_template.go @@ -68,7 +68,7 @@ func ResourceTencentCloudVodSnapshotByTimeOffsetTemplate() *schema.Resource { "sub_app_id": { Type: schema.TypeInt, Optional: true, - Description: "Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty.", + Description: "The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID.", }, "fill_type": { Type: schema.TypeString, diff --git a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown index 156ab1e7db..01e00af27e 100644 --- a/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown +++ b/website/docs/r/vod_adaptive_dynamic_streaming_template.html.markdown @@ -59,7 +59,7 @@ The following arguments are supported: * `disable_higher_video_bitrate` - (Optional, Bool) Whether to prohibit transcoding video from low bitrate to high bitrate. Valid values: `false`,`true`. `false`: no, `true`: yes. Default value: `false`. * `disable_higher_video_resolution` - (Optional, Bool) Whether to prohibit transcoding from low resolution to high resolution. Valid values: `false`,`true`. `false`: no, `true`: yes. Default value: `false`. * `drm_type` - (Optional, String, ForceNew) DRM scheme type. Valid values: `SimpleAES`. If this field is an empty string, DRM will not be performed on the video. -* `sub_app_id` - (Optional, Int) Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty. +* `sub_app_id` - (Optional, Int) The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID. The `audio` object of `stream_info` supports the following: diff --git a/website/docs/r/vod_image_sprite_template.html.markdown b/website/docs/r/vod_image_sprite_template.html.markdown index 271c77a9fd..345783bd05 100644 --- a/website/docs/r/vod_image_sprite_template.html.markdown +++ b/website/docs/r/vod_image_sprite_template.html.markdown @@ -53,7 +53,7 @@ The following arguments are supported: Default value: jpg. * `height` - (Optional, Int) Maximum value of the `height` (or short side) of a screenshot in px. Value range: 0 and [128, 4,096]. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, `width` will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. * `resolution_adaptive` - (Optional, Bool) Resolution adaption. Valid values: `true`,`false`. `true`: enabled. In this case, `width` represents the long side of a video, while `height` the short side; `false`: disabled. In this case, `width` represents the width of a video, while `height` the height. Default value: `true`. -* `sub_app_id` - (Optional, Int) Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty. +* `sub_app_id` - (Optional, Int) The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID. * `width` - (Optional, Int) Maximum value of the `width` (or long side) of a screenshot in px. Value range: 0 and [128, 4,096]. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, width will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. ## Attributes Reference diff --git a/website/docs/r/vod_procedure_template.html.markdown b/website/docs/r/vod_procedure_template.html.markdown index 42f1fad29f..659db1466a 100644 --- a/website/docs/r/vod_procedure_template.html.markdown +++ b/website/docs/r/vod_procedure_template.html.markdown @@ -150,7 +150,7 @@ The following arguments are supported: * `comment` - (Optional, String) Template description. Length limit: 256 characters. * `media_process_task` - (Optional, List) Parameter of video processing task. * `review_audio_video_task` - (Optional, List) Type parameter of AI-based content recognition task. -* `sub_app_id` - (Optional, Int) Subapplication ID in VOD. For customers who activate VOD from December 25, 2023, if they access the resources in the VOD application (whether it is the default application or the newly created application), you must fill in this field as Application ID. +* `sub_app_id` - (Optional, Int) The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID. The `adaptive_dynamic_streaming_task_list` object of `media_process_task` supports the following: diff --git a/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown b/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown index 5eb5ca4a15..c18837bc2f 100644 --- a/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown +++ b/website/docs/r/vod_snapshot_by_time_offset_template.html.markdown @@ -35,7 +35,7 @@ The following arguments are supported: * `format` - (Optional, String) Image format. Valid values: `jpg`, `png`. Default value: `jpg`. * `height` - (Optional, Int) Maximum value of the `height` (or short side) of a screenshot in px. Value range: 0 and [128, 4,096]. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, `width` will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. * `resolution_adaptive` - (Optional, Bool) Resolution adaption. Valid values: `true`,`false`. `true`: enabled. In this case, `width` represents the long side of a video, while `height` the short side; `false`: disabled. In this case, `width` represents the width of a video, while `height` the height. Default value: `true`. -* `sub_app_id` - (Optional, Int) Subapplication ID in VOD. If you need to access a resource in a subapplication, enter the subapplication ID in this field; otherwise, leave it empty. +* `sub_app_id` - (Optional, Int) The VOD [application](https://intl.cloud.tencent.com/document/product/266/14574) ID. For customers who activate VOD service from December 25, 2023, if they want to access resources in a VOD application (whether it's the default application or a newly created one), they must fill in this field with the application ID. * `width` - (Optional, Int) Maximum value of the `width` (or long side) of a screenshot in px. Value range: 0 and [128, 4,096]. If both `width` and `height` are `0`, the resolution will be the same as that of the source video; If `width` is `0`, but `height` is not `0`, width will be proportionally scaled; If `width` is not `0`, but `height` is `0`, `height` will be proportionally scaled; If both `width` and `height` are not `0`, the custom resolution will be used. Default value: `0`. ## Attributes Reference From af3c748098dcead165bd9ffd0c1d405f6c509ae9 Mon Sep 17 00:00:00 2001 From: mikatong Date: Mon, 25 Mar 2024 16:31:01 +0800 Subject: [PATCH 9/9] update --- .../vod/resource_tc_vod_sample_snapshot_template.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go index a89c836780..4b86cead3f 100644 --- a/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go +++ b/tencentcloud/services/vod/resource_tc_vod_sample_snapshot_template.go @@ -301,7 +301,13 @@ func resourceTencentCloudVodSampleSnapshotTemplateUpdate(d *schema.ResourceData, err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVodClient().ModifySampleSnapshotTemplate(request) if e != nil { - return tccommon.RetryError(e) + if sdkError, ok := e.(*sdkErrors.TencentCloudSDKError); ok { + if sdkError.Code == "FailedOperation" && sdkError.Message == "invalid vod user" { + return resource.RetryableError(e) + } + } + log.Printf("[CRITAL]%s api[%s] fail, reason:%s", logId, request.GetAction(), e.Error()) + return resource.NonRetryableError(e) } else { log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) }