diff --git a/docs/data-sources/live_channels.md b/docs/data-sources/live_channels.md
new file mode 100644
index 00000000000..64bec001429
--- /dev/null
+++ b/docs/data-sources/live_channels.md
@@ -0,0 +1,392 @@
+---
+subcategory: "Live"
+layout: "huaweicloud"
+page_title: "HuaweiCloud: huaweicloud_live_channels"
+description: |-
+ Use this data source to get the list of Live channels within HuaweiCloud.
+---
+
+# huaweicloud_live_channels
+
+Use this data source to get the list of Live channels within HuaweiCloud.
+
+## Example Usage
+
+```hcl
+data "huaweicloud_live_channels" "test" {
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `region` - (Optional, String) Specifies the region in which to query the resource.
+ If omitted, the provider-level region will be used.
+
+* `domain_name` - (Optional, String) Specifies the channel streaming domain name.
+
+* `app_name` - (Optional, String) Specifies the group name or application name.
+
+* `channel_id` - (Optional, String) Specifies the channel ID.
+
+## Attribute Reference
+
+In addition to all arguments above, the following attributes are exported:
+
+* `id` - The data source ID.
+
+* `channels` - The channel information.
+
+ The [channels](#channels_struct) structure is documented below.
+
+
+The `channels` block supports:
+
+* `domain_name` - The channel streaming domain name.
+
+* `app_name` - The group name or application name.
+
+* `state` - The channel status. Valid values are:
+ + **ON**: After a channel is delivered, functions such as stream pull, transcoding, and recording are automatically enabled.
+ + **OFF**: Only the channel information is saved but the channel is not started.
+
+* `input` - The channel input information.
+ The [input](#LiveChannel_Input) structure is documented below.
+
+* `record_settings` - The configuration for replaying a recording.
+ The [record_settings](#LiveChannel_RecordSettings) structure is documented below.
+
+* `endpoints` - The channel outflow information.
+ The [endpoints](#LiveChannel_Endpoints) structure is documented below.
+
+* `encoder_settings_expand` - The audio output configuration.
+ The [encoder_settings_expand](#LiveChannel_EncoderSettingsExpand) structure is documented below.
+
+* `encoder_settings` - The transcoding template configuration.
+ The [encoder_settings](#LiveChannel_EncoderSettings) structure is documented below.
+
+* `name` - The channel name. The name can be duplicated.
+
+* `id` - The channel ID.
+
+
+The `input` block supports:
+
+* `input_protocol` - The channel input protocol. Valid values are:
+ + **FLV_PULL**.
+ + **RTMP_PUSH**.
+ + **HLS_PULL**.
+ + **SRT_PULL**.
+ + **SRT_PUSH**.
+
+* `sources` - The channel main source stream information.
+ The [sources](#LiveChannel_Sources) structure is documented below.
+
+* `secondary_sources` - The prepared stream array.
+ The [secondary_sources](#LiveChannel_SecondarySources) structure is documented below.
+
+* `failover_conditions` - The configuration of switching between primary and backup audio and video stream URLs.
+ The [failover_conditions](#LiveChannel_FailoverConditions) structure is documented below.
+
+* `max_bandwidth_limit` - The maximum bandwidth that needs to be configured when the inbound protocol is **HLS_PULL**.
+ The unit is **bps**.
+
+* `ip_port_mode` - The IP port mode.
+
+* `ip_whitelist` - The IP whitelist when protocol is **SRT_PUSH**.
+
+* `scte35_source` - The advertisement scte35 signal source.
+
+* `ad_triggers` - The ad trigger configuration list. Valid Values are:
+ + **Splice insert**.
+ + **Provider advertisement**.
+ + **Distributor advertisement**.
+ + **Provider placement opportunity**.
+ + **Distributor placement opportunity**.
+
+* `audio_selectors` - The audio selector configuration.
+ The [audio_selectors](#LiveChannel_AudioSelectors) structure is documented below.
+
+
+The `sources` block supports:
+
+* `url` - The channel source stream URL, used for external streaming.
+
+* `bitrate` - The bitrate. The unit is **bps**.
+
+* `width` - The resolution corresponds to the width value.
+
+* `height` - The resolution corresponds to the high value.
+
+* `enable_snapshot` - Whether to use this stream to take screenshots.
+
+* `bitrate_for3u8` - Whether to use bitrate to fix the bitrate.
+
+* `passphrase` - The encrypted information when the protocol is **SRT_PUSH**.
+
+* `backup_urls` - The list of backup stream addresses.
+
+* `stream_id` - The stream ID of the stream pull address when the channel type is **SRT_PULL**.
+
+* `latency` - The streaming delay when the channel type is **SRT_PULL**.
+
+
+The `secondary_sources` block supports:
+
+* `url` - The channel source stream URL, used for external streaming.
+
+* `bitrate` - The bitrate. The unit is **bps**.
+
+* `width` - The resolution corresponds to the width value.
+
+* `height` - The resolution corresponds to the high value.
+
+* `bitrate_for3u8` - Whether to use bitrate to fix the bitrate.
+
+* `passphrase` - The encrypted information when the protocol is **SRT_PUSH**.
+
+* `backup_urls` - The list of backup stream addresses.
+
+* `stream_id` - The stream ID of the stream pull address when the channel type is **SRT_PULL**.
+
+* `latency` - The streaming delay when the channel type is **SRT_PULL**.
+
+
+The `failover_conditions` block supports:
+
+* `input_loss_threshold_msec` - The duration threshold of inflow stop. The unit is millisecond.
+
+* `input_preference` - The input preference type. Valid values are:
+ + **PRIMARY**: The main incoming URL is the first priority.
+ + **EQUAL**: Equal switching between primary and backup URLs.
+
+
+The `audio_selectors` block supports:
+
+* `name` - The name of the audio selector.
+
+* `selector_settings` - The audio selector configuration.
+ The [selector_settings](#LiveChannel_SelectorSettings) structure is documented below.
+
+
+The `selector_settings` block supports:
+
+* `audio_language_selection` - The language selector configuration.
+ The [audio_language_selection](#LiveChannel_AudioLanguageSelection) structure is documented below.
+
+* `audio_pid_selection` - The PID selector configuration.
+ The [audio_pid_selection](#LiveChannel_AudioPidSelection) structure is documented below.
+
+* `audio_hls_selection` - The HLS selector configuration.
+ The [audio_hls_selection](#LiveChannel_AudioHlsSelection) structure is documented below.
+
+
+The `audio_language_selection` block supports:
+
+* `language_code` - The language abbreviation. Supports `2` or `3` lowercase letter language codes.
+
+* `language_selection_policy` - The language output strategy. Valid values are:
+ + **LOOSE**: Loose matching. For example, "eng" will prioritize matching tracks with English as the language in the
+ source stream. If no match is found, the track with the smallest PID will be selected.
+ + **STRICT**: Strict matching. For example, "eng" will strictly match the audio track in the source stream whose
+ language is English. If no match is found, the media live broadcast service will automatically fill in a silent
+ segment. When the terminal uses this audio selector to play the video, it will be played silently.
+
+
+The `audio_pid_selection` block supports:
+
+* `pid` - The value of PID.
+
+
+The `audio_hls_selection` block supports:
+
+* `name` - The HLS audio selector name.
+
+* `group_id` - The HLS audio selector gid.
+
+
+The `record_settings` block supports:
+
+* `rollingbuffer_duration` - The maximum playback recording time. During this time period, the recording will continue.
+ The unit is second.
+
+
+The `endpoints` block supports:
+
+* `hls_package` - The HLS packaging information.
+ The [hls_package](#LiveChannel_HlsPackage) structure is documented below.
+
+* `dash_package` - The DASH packaging information.
+ The [dash_package](#LiveChannel_DashPackage) structure is documented below.
+
+* `mss_package` - The MSS packaging information.
+ The [mss_package](#LiveChannel_MssPackage) structure is documented below.
+
+
+The `hls_package` block supports:
+
+* `url` - The customer-defined streaming address, including method, domain name, and path.
+
+* `stream_selection` - The stream selection. Filter out the specified range of streams from the full stream.
+ The [stream_selection](#LiveChannel_StreamSelection) structure is documented below.
+
+* `hls_version` - The HLS version.
+
+* `segment_duration_seconds` - The duration of the channel output segment. The unit is second.
+
+* `playlist_window_seconds` - The window length of the channel live broadcast return shard. The unit is second.
+
+* `encryption` - The encrypted information.
+ The [encryption](#LiveChannel_Encryption) structure is documented below.
+
+* `request_args` - The play related configuration.
+ The [request_args](#LiveChannel_RequestArgs) structure is documented below.
+
+* `ad_marker` - The advertising marker.
+
+
+The `dash_package` block supports:
+
+* `url` - The customer-defined streaming address, including method, domain name, and path.
+
+* `stream_selection` - The stream selection. Filter out the specified range of streams from the full stream.
+ The [stream_selection](#LiveChannel_StreamSelection) structure is documented below.
+
+* `segment_duration_seconds` - The duration of the channel output segment. The unit is second.
+
+* `playlist_window_seconds` - The window length of the channel live broadcast return shard. The unit is second.
+
+* `encryption` - The encrypted information.
+ The [encryption](#LiveChannel_Encryption) structure is documented below.
+
+* `request_args` - The play related configuration.
+ The [request_args](#LiveChannel_RequestArgs) structure is documented below.
+
+* `ad_marker` - The advertising marker.
+
+
+The `mss_package` block supports:
+
+* `url` - The customer-defined streaming address, including method, domain name, and path.
+
+* `stream_selection` - The stream selection. Filter out the specified range of streams from the full stream.
+ The [stream_selection](#LiveChannel_StreamSelection) structure is documented below.
+
+* `segment_duration_seconds` - The duration of the channel output segment. The unit is second.
+
+* `playlist_window_seconds` - The window length of the channel live broadcast return shard. The unit is second.
+
+* `encryption` - The encrypted information.
+ The [encryption](#LiveChannel_Encryption) structure is documented below.
+
+* `delay_segment` - The delayed playback time. The unit is second.
+
+* `request_args` - The play related configuration.
+ The [request_args](#LiveChannel_RequestArgs) structure is documented below.
+
+
+The `stream_selection` block supports:
+
+* `key` - The key used for bitrate filtering in streaming URLs.
+
+* `max_bandwidth` - The maximum code rate. The unit is bps.
+
+* `min_bandwidth` - The minimum code rate. The unit is bps.
+
+
+The `encryption` block supports:
+
+* `level` - The level. Valid values are:
+ + **content**: One channel corresponds to one key.
+ + **profile**: One code rate corresponds to one key.
+
+* `resource_id` - The customer-generated DRM content ID.
+
+* `system_ids` - The system ID enumeration values. Valid values are **FairPlay** (HLS),
+ **Widevine** (DASH), **PlayReady** (DASH), and **PlayReady** (MSS).
+
+* `url` - The DRM address of the key.
+
+* `speke_version` - The DRM spec version number.
+
+* `request_mode` - The request mode. Valid values are:
+ + **direct_http**: HTTP(S) direct access to DRM.
+ + **functiongraph_proxy**: FunctionGraph proxy access to DRM.
+
+* `http_headers` - The authentication information that needs to be added to the DRM request header.
+ The [http_headers](#LiveChannel_HttpHeader) structure is documented below.
+
+* `urn` - The URN of the function graph.
+
+
+The `http_headers` block supports:
+
+* `key` - The key field name in the request header.
+
+* `value` - The value corresponding to the key in the request header.
+
+
+The `request_args` block supports:
+
+* `record` - The recording and playback related configuration.
+ The [record](#LiveChannel_RequestArgsRecord) structure is documented below.
+
+* `timeshift` - The time-shift playback configuration.
+ The [timeshift](#LiveChannel_RequestArgsTimeShift) structure is documented below.
+
+* `live` - The live broadcast configuration.
+ The [live](#LiveChannel_RequestArgsLive) structure is documented below.
+
+
+The `record` block supports:
+
+* `start_time` - The start time.
+
+* `end_time` - The end time.
+
+* `format` - The format.
+
+* `unit` - The unit.
+
+
+The `timeshift` block supports:
+
+* `back_time` - The time shift duration field name.
+
+* `unit` - The unit.
+
+
+The `live` block supports:
+
+* `delay` - The delay field.
+
+* `unit` - The unit.
+
+
+The `encoder_settings_expand` block supports:
+
+* `audio_descriptions` - The description of the audio output configuration.
+ The [audio_descriptions](#LiveChannel_AudioDescriptions) structure is documented below.
+
+
+The `audio_descriptions` block supports:
+
+* `name` - The name of the audio output configuration.
+
+* `audio_selector_name` - The audio selector name.
+
+* `language_code_control` - The language code control configuration. Valid values are:
+ + **FOLLOW_INPUT**: If the output audio corresponding to the selected audio selector has a language, it will be
+ consistent with it, otherwise it will be backed up by the language code and stream name configured here.
+ The current option is recommended and is the default value.
+ + **USE_CONFIGURED**: Users can customize the language and stream name of the output audio based on actual conditions.
+
+* `language_code` - The language code.
+
+* `stream_name` - The stream name.
+
+
+The `encoder_settings` block supports:
+
+* `template_id` - The transcoding template ID.
diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go
index aed756698f4..8eec42ada85 100644
--- a/huaweicloud/provider.go
+++ b/huaweicloud/provider.go
@@ -921,6 +921,7 @@ func Provider() *schema.Provider {
"huaweicloud_live_snapshots": live.DataSourceLiveSnapshots(),
"huaweicloud_live_geo_blockings": live.DataSourceGeoBlockings(),
"huaweicloud_live_record_callbacks": live.DataSourceLiveRecordCallbacks(),
+ "huaweicloud_live_channels": live.DataSourceLiveChannels(),
"huaweicloud_lts_aom_accesses": lts.DataSourceAOMAccesses(),
"huaweicloud_lts_cce_accesses": lts.DataSourceCceAccesses(),
diff --git a/huaweicloud/services/acceptance/live/data_source_huaweicloud_live_channels_test.go b/huaweicloud/services/acceptance/live/data_source_huaweicloud_live_channels_test.go
new file mode 100644
index 00000000000..c0e040a45e9
--- /dev/null
+++ b/huaweicloud/services/acceptance/live/data_source_huaweicloud_live_channels_test.go
@@ -0,0 +1,133 @@
+package live
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
+)
+
+func TestAccDataSourceChannels_basic(t *testing.T) {
+ var (
+ rName = acceptance.RandomAccResourceName()
+
+ dataSource = "data.huaweicloud_live_channels.test"
+ dc = acceptance.InitDataSourceCheck(dataSource)
+
+ byDomainName = "data.huaweicloud_live_channels.filter_by_domain_name"
+ dcByDomainName = acceptance.InitDataSourceCheck(byDomainName)
+
+ byAppName = "data.huaweicloud_live_channels.filter_by_app_name"
+ dcByAppName = acceptance.InitDataSourceCheck(byAppName)
+
+ byChannelID = "data.huaweicloud_live_channels.filter_by_channel_id"
+ dcByChannelID = acceptance.InitDataSourceCheck(byChannelID)
+ )
+
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() {
+ acceptance.TestAccPreCheck(t)
+ acceptance.TestAccPreCheckLiveStreamingDomainName(t)
+ acceptance.TestAccPreCheckLiveIngestRTMPDomainName(t)
+ acceptance.TestAccPreCheckLiveTranscodingTemplateID(t)
+ },
+ ProviderFactories: acceptance.TestAccProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testDataSourceChannels_basic(rName),
+ Check: resource.ComposeTestCheckFunc(
+ dc.CheckResourceExists(),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.app_name"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.domain_name"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.encoder_settings.#"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.endpoints.#"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.id"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.input.#"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.name"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.record_settings.#"),
+ resource.TestCheckResourceAttrSet(dataSource, "channels.0.state"),
+
+ dcByDomainName.CheckResourceExists(),
+ resource.TestCheckOutput("domain_name_filter_is_useful", "true"),
+
+ dcByAppName.CheckResourceExists(),
+ resource.TestCheckOutput("app_name_filter_is_useful", "true"),
+
+ dcByChannelID.CheckResourceExists(),
+ resource.TestCheckOutput("channel_id_filter_is_useful", "true"),
+ ),
+ },
+ },
+ })
+}
+
+func testDataSourceChannels_basic(name string) string {
+ return fmt.Sprintf(`
+%s
+
+data "huaweicloud_live_channels" "test" {
+ depends_on = [
+ huaweicloud_live_channel.test
+ ]
+}
+
+# Filter by domain_name
+locals {
+ domain_name = data.huaweicloud_live_channels.test.channels[0].domain_name
+}
+
+data "huaweicloud_live_channels" "filter_by_domain_name" {
+ domain_name = local.domain_name
+}
+
+locals {
+ domain_name_filter_result = [
+ for v in data.huaweicloud_live_channels.filter_by_domain_name.channels[*].domain_name : v == local.domain_name
+ ]
+}
+
+output "domain_name_filter_is_useful" {
+ value = alltrue(local.domain_name_filter_result) && length(local.domain_name_filter_result) > 0
+}
+
+# Filter by app_name
+locals {
+ app_name = data.huaweicloud_live_channels.test.channels[0].app_name
+}
+
+data "huaweicloud_live_channels" "filter_by_app_name" {
+ app_name = local.app_name
+}
+
+locals {
+ app_name_filter_result = [
+ for v in data.huaweicloud_live_channels.filter_by_app_name.channels[*].app_name : v == local.app_name
+ ]
+}
+
+output "app_name_filter_is_useful" {
+ value = alltrue(local.app_name_filter_result) && length(local.app_name_filter_result) > 0
+}
+
+# Filter by channel_id
+locals {
+ channel_id = data.huaweicloud_live_channels.test.channels[0].id
+}
+
+data "huaweicloud_live_channels" "filter_by_channel_id" {
+ channel_id = local.channel_id
+}
+
+locals {
+ channel_id_filter_result = [
+ for v in data.huaweicloud_live_channels.filter_by_channel_id.channels[*].id : v == local.channel_id
+ ]
+}
+
+output "channel_id_filter_is_useful" {
+ value = alltrue(local.channel_id_filter_result) && length(local.channel_id_filter_result) > 0
+}
+`, testLiveChannel_FLV_PULL(name))
+}
diff --git a/huaweicloud/services/live/data_source_huaweicloud_live_channels.go b/huaweicloud/services/live/data_source_huaweicloud_live_channels.go
new file mode 100644
index 00000000000..9008a23c93f
--- /dev/null
+++ b/huaweicloud/services/live/data_source_huaweicloud_live_channels.go
@@ -0,0 +1,1365 @@
+package live
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/go-uuid"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
+ "github.com/chnsz/golangsdk"
+
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
+)
+
+// @API LIVE GET /v1/{project_id}/ott/channels
+func DataSourceLiveChannels() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceLiveChannelsRead,
+
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: `Specifies the region in which to query the resource. If omitted, the provider-level region will be used.`,
+ },
+ "domain_name": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: `Specifies the channel streaming domain name.`,
+ },
+ "app_name": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: `Specifies the group name or application name.`,
+ },
+ "channel_id": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: `Specifies the channel ID.`,
+ },
+ "channels": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: `The channel information.`,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "domain_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel streaming domain name.`,
+ },
+ "app_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The group name or application name.`,
+ },
+ "state": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel status.`,
+ },
+ "input": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelInputSchema(),
+ Description: `The channel input information.`,
+ },
+ "record_settings": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelRecordSettingsSchema(),
+ Description: `The configuration for replaying a recording.`,
+ },
+ "endpoints": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsSchema(),
+ Description: `The channel outflow information.`,
+ },
+ "encoder_settings_expand": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEncoderSettingsExpandSchema(),
+ Description: `The audio output configuration.`,
+ },
+ "encoder_settings": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEncoderSettingsSchema(),
+ Description: `The transcoding template configuration.`,
+ },
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel name.`,
+ },
+ "id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel ID.`,
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func dataChannelEncoderSettingsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "template_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The transcoding template ID.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEncoderSettingsExpandSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "audio_descriptions": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEncoderSettingsExpandAudioDescriptionsSchema(),
+ Description: `The description of the audio output configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEncoderSettingsExpandAudioDescriptionsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The name of the audio output configuration.`,
+ },
+ "audio_selector_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The audio selector name.`,
+ },
+ "language_code_control": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The language code control configuration.`,
+ },
+ "language_code": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The language code.`,
+ },
+ "stream_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The stream name.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "hls_package": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsHlsPackageSchema(),
+ Description: `The HLS packaging information.`,
+ },
+ "dash_package": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsDashPackageSchema(),
+ Description: `The DASH packaging information.`,
+ },
+ "mss_package": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsMssPackageSchema(),
+ Description: `The MSS packaging information.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsMssPackageSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The customer-defined streaming address.`,
+ },
+ "stream_selection": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsStreamSelectionSchema(),
+ Computed: true,
+ Description: `The stream selection.`,
+ },
+ "segment_duration_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The duration of the channel output segment.`,
+ },
+ "playlist_window_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The window length of the channel live broadcast return shard.`,
+ },
+ "encryption": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsEncryptionSchema(),
+ Computed: true,
+ Description: `The encrypted information.`,
+ },
+ "delay_segment": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The delayed playback time.`,
+ },
+ "request_args": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsRequestArgsSchema(),
+ Computed: true,
+ Description: `The play related configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsDashPackageSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The customer-defined streaming address.`,
+ },
+ "stream_selection": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsStreamSelectionSchema(),
+ Computed: true,
+ Description: `The stream selection.`,
+ },
+ "segment_duration_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The duration of the channel output segment.`,
+ },
+ "playlist_window_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The window length of the channel live broadcast return shard.`,
+ },
+ "encryption": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsEncryptionSchema(),
+ Computed: true,
+ Description: `The encrypted information.`,
+ },
+ "request_args": {
+ Type: schema.TypeList,
+ Elem: dataChannelEndpointsRequestArgsSchema(),
+ Computed: true,
+ Description: `The play related configuration.`,
+ },
+ "ad_marker": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The advertising marker.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsHlsPackageSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The customer-defined streaming address.`,
+ },
+ "segment_duration_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The duration of the channel output segment.`,
+ },
+ "stream_selection": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsStreamSelectionSchema(),
+ Description: `The stream selection.`,
+ },
+ "hls_version": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The HLS version number.`,
+ },
+ "playlist_window_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The window length of the channel live broadcast return shard.`,
+ },
+ "encryption": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsEncryptionSchema(),
+ Description: `The encrypted information.`,
+ },
+ "request_args": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEndpointsRequestArgsSchema(),
+ Description: `The play related configuration.`,
+ },
+ "ad_marker": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: `The advertising marker.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsRequestArgsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "record": {
+ Type: schema.TypeList,
+ Elem: dataChannelRequestArgsRecordSchema(),
+ Computed: true,
+ Description: `The recording and playback related configuration.`,
+ },
+ "timeshift": {
+ Type: schema.TypeList,
+ Elem: dataChannelRequestArgsTimeShiftSchema(),
+ Computed: true,
+ Description: `The time-shift playback configuration.`,
+ },
+ "live": {
+ Type: schema.TypeList,
+ Elem: dataChannelRequestArgsLiveSchema(),
+ Computed: true,
+ Description: `The live broadcast configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelRequestArgsLiveSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "delay": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The delay field.`,
+ },
+ "unit": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The unit.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelRequestArgsTimeShiftSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "back_time": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The time shift duration field name.`,
+ },
+ "unit": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The unit.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelRequestArgsRecordSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "start_time": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The start time.`,
+ },
+ "end_time": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The end time.`,
+ },
+ "format": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The format.`,
+ },
+ "unit": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The unit.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsEncryptionSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "resource_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The customer-generated DRM content ID.`,
+ },
+ "system_ids": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: `The system ID enumeration values.`,
+ },
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The DRM address of the key.`,
+ },
+ "speke_version": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The DRM spec version number.`,
+ },
+ "request_mode": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The request mode.`,
+ },
+ "key_rotation_interval_seconds": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The key rotation interval seconds.`,
+ },
+ "encryption_method": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The encryption method.`,
+ },
+ "level": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The level.`,
+ },
+ "http_headers": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelEncryptionHttpHeaderSchema(),
+ Description: `The authentication information that needs to be added to the DRM request header.`,
+ },
+ "urn": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The URN of the function graph.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEncryptionHttpHeaderSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "key": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The key field name in the request header.`,
+ },
+ "value": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The value corresponding to the key in the request header.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelEndpointsStreamSelectionSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "key": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The key used for bitrate filtering in streaming URLs.`,
+ },
+ "max_bandwidth": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The maximum code rate.`,
+ },
+ "min_bandwidth": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The minimum code rate.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelRecordSettingsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "rollingbuffer_duration": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The maximum playback recording time.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelInputSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "input_protocol": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel input protocol.`,
+ },
+ "sources": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelInputSourcesSchema(),
+ Description: `The channel main source stream information.`,
+ },
+ "secondary_sources": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelInputSecondarySourcesSchema(),
+ Description: `The prepared stream array.`,
+ },
+ "failover_conditions": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelInputFailoverConditionsSchema(),
+ Description: `The configuration of switching between primary and backup audio and video stream URLs.`,
+ },
+ "max_bandwidth_limit": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The maximum bandwidth that needs to be configured when the inbound protocol is **HLS_PULL**.`,
+ },
+ "ip_port_mode": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `The IP port mode.`,
+ },
+ "ip_whitelist": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The IP whitelist when protocol is **SRT_PUSH**.`,
+ },
+ "scte35_source": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The advertisement scte35 signal source.`,
+ },
+ "ad_triggers": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: `The ad trigger configuration.`,
+ },
+ "audio_selectors": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelInputAudioSelectorsSchema(),
+ Description: `The audio selector configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelInputSourcesSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel source stream URL, used for external streaming.`,
+ },
+ "bitrate": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The bitrate.`,
+ },
+ "width": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The resolution corresponds to the width value.`,
+ },
+ "height": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The resolution corresponds to the high value.`,
+ },
+ "enable_snapshot": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `Whether to use this stream to take screenshots.`,
+ },
+ "bitrate_for3u8": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `Whether to use bitrate to fix the bitrate.`,
+ },
+ "passphrase": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The encrypted information when the protocol is **SRT_PUSH**.`,
+ },
+ "backup_urls": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: `The list of backup stream addresses.`,
+ },
+ "stream_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The stream ID of the stream pull address when the channel type is **SRT_PULL**.`,
+ },
+ "latency": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The streaming delay when the channel type is **SRT_PULL**.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelInputSecondarySourcesSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The channel source stream URL.`,
+ },
+ "bitrate": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The bitrate.`,
+ },
+ "width": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The resolution corresponds to the width value.`,
+ },
+ "height": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The resolution corresponds to the high value.`,
+ },
+ "bitrate_for3u8": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `Whether to use bitrate to fix the bitrate.`,
+ },
+ "passphrase": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The encrypted information when the protocol is **SRT_PUSH**.`,
+ },
+ "backup_urls": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ Description: `The list of backup stream addresses.`,
+ },
+ "stream_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The stream ID of the stream pull address when the channel type is **SRT_PULL**.`,
+ },
+ "latency": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The streaming delay when the channel type is **SRT_PULL**.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelInputFailoverConditionsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "input_loss_threshold_msec": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The duration threshold of inflow stop.`,
+ },
+ "input_preference": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The input preference type.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelInputAudioSelectorsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The name of the audio selector.`,
+ },
+ "selector_settings": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelAudioSelectorsSelectorSettingsSchema(),
+ Description: `The audio selector configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelAudioSelectorsSelectorSettingsSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "audio_language_selection": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelSelectorSettingsAudioLanguageSelectionSchema(),
+ Description: `The language selector configuration.`,
+ },
+ "audio_pid_selection": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelSelectorSettingsAudioPidSelectionSchema(),
+ Description: `The PID selector configuration.`,
+ },
+ "audio_hls_selection": {
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: dataChannelSelectorSettingsAudioHlsSelectionSchema(),
+ Description: `The HLS selector configuration.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelSelectorSettingsAudioLanguageSelectionSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "language_code": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The language abbreviation.`,
+ },
+ "language_selection_policy": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The language output strategy.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelSelectorSettingsAudioPidSelectionSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "pid": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The value of PID.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func dataChannelSelectorSettingsAudioHlsSelectionSchema() *schema.Resource {
+ sc := schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The HLS audio selector name.`,
+ },
+ "group_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The HLS audio selector gid.`,
+ },
+ },
+ }
+ return &sc
+}
+
+func buildDatasourceChannelQueryParams(d *schema.ResourceData) string {
+ res := ""
+ if v, ok := d.GetOk("domain_name"); ok {
+ res = fmt.Sprintf("%s&domain=%v", res, v)
+ }
+
+ if v, ok := d.GetOk("app_name"); ok {
+ res = fmt.Sprintf("%s&app_name=%v", res, v)
+ }
+
+ if v, ok := d.GetOk("channel_id"); ok {
+ res = fmt.Sprintf("%s&id=%v", res, v)
+ }
+ return res
+}
+
+func dataSourceLiveChannelsRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ var (
+ cfg = meta.(*config.Config)
+ region = cfg.GetRegion(d)
+ httpUrl = "v1/{project_id}/ott/channels?limit=100"
+ product = "live"
+ totalChannels []interface{}
+ offset = 0
+ )
+ client, err := cfg.NewServiceClient(product, region)
+ if err != nil {
+ return diag.Errorf("error creating Live client: %s", err)
+ }
+
+ requestPath := client.Endpoint + httpUrl
+ requestPath = strings.ReplaceAll(requestPath, "{project_id}", client.ProjectID)
+ requestPath += buildDatasourceChannelQueryParams(d)
+ requestOpt := golangsdk.RequestOpts{
+ KeepResponseBody: true,
+ MoreHeaders: map[string]string{"Content-Type": "application/json"},
+ }
+
+ for {
+ requestPathWithOffset := fmt.Sprintf("%s&offset=%d", requestPath, offset)
+ resp, err := client.Request("GET", requestPathWithOffset, &requestOpt)
+ if err != nil {
+ return diag.Errorf("error retrieving Live channels: %s", err)
+ }
+
+ respBody, err := utils.FlattenResponse(resp)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ channels := utils.PathSearch("channels", respBody, make([]interface{}, 0)).([]interface{})
+ if len(channels) == 0 {
+ break
+ }
+
+ totalChannels = append(totalChannels, channels...)
+ offset += len(channels)
+ }
+
+ dataSourceId, err := uuid.GenerateUUID()
+ if err != nil {
+ return diag.Errorf("unable to generate ID: %s", err)
+ }
+ d.SetId(dataSourceId)
+
+ mErr := multierror.Append(nil,
+ d.Set("region", region),
+ d.Set("channels", flattenDataSourceChannels(totalChannels)),
+ )
+ return diag.FromErr(mErr.ErrorOrNil())
+}
+
+func flattenDataSourceChannels(totalChannels []interface{}) []interface{} {
+ if len(totalChannels) == 0 {
+ return nil
+ }
+
+ result := make([]interface{}, 0, len(totalChannels))
+ for _, v := range totalChannels {
+ result = append(result, map[string]interface{}{
+ "domain_name": utils.PathSearch("domain", v, nil),
+ "app_name": utils.PathSearch("app_name", v, nil),
+ "id": utils.PathSearch("id", v, nil),
+ "name": utils.PathSearch("name", v, nil),
+ "state": utils.PathSearch("state", v, nil),
+ "input": flattenDataChannelInputResponseBody(v),
+ "encoder_settings": flattenDataChannelEncoderSettingsResponseBody(v),
+ "record_settings": flattenDataChannelRecordSettingsResponseBody(v),
+ "endpoints": flattenDataChannelEndpointsResponseBody(v),
+ "encoder_settings_expand": flattenDataChannelEncoderSettingsExpandResponseBody(v),
+ })
+ }
+ return result
+}
+
+func flattenDataChannelEncoderSettingsExpandResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("encoder_settings_expand", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "audio_descriptions": flattenDataAudioDescriptionsResponseBody(respBody),
+ }}
+}
+
+func flattenDataAudioDescriptionsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("audio_descriptions", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "name": utils.PathSearch("name", v, nil),
+ "audio_selector_name": utils.PathSearch("audio_selector_name", v, nil),
+ "language_code_control": utils.PathSearch("language_code_control", v, nil),
+ "language_code": utils.PathSearch("language_code", v, nil),
+ "stream_name": utils.PathSearch("stream_name", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataChannelEndpointsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("endpoints", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "hls_package": flattenDataHlsPackageResponseBody(v),
+ "dash_package": flattenDataDashPackageResponseBody(v),
+ "mss_package": flattenDataMssPackageResponseBody(v),
+ })
+ }
+ return rst
+}
+
+func flattenDataMssPackageResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("mss_package", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "url": utils.PathSearch("url", v, nil),
+ "stream_selection": flattenDataStreamSelectionResponseBody(v),
+ "segment_duration_seconds": utils.PathSearch("segment_duration_seconds", v, nil),
+ "playlist_window_seconds": utils.PathSearch("playlist_window_seconds", v, nil),
+ "encryption": flattenDataEncryptionResponseBody(v),
+ "delay_segment": utils.PathSearch("delay_segment", v, nil),
+ "request_args": flattenDataRequestArgsResponseBody(v),
+ })
+ }
+ return rst
+}
+
+func flattenDataDashPackageResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("dash_package", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "url": utils.PathSearch("url", v, nil),
+ "stream_selection": flattenDataStreamSelectionResponseBody(v),
+ "segment_duration_seconds": utils.PathSearch("segment_duration_seconds", v, nil),
+ "playlist_window_seconds": utils.PathSearch("playlist_window_seconds", v, nil),
+ "encryption": flattenDataEncryptionResponseBody(v),
+ "request_args": flattenDataRequestArgsResponseBody(v),
+ "ad_marker": utils.PathSearch("ad_marker", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataHlsPackageResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("hls_package", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "url": utils.PathSearch("url", v, nil),
+ "stream_selection": flattenDataStreamSelectionResponseBody(v),
+ "hls_version": utils.PathSearch("hls_version", v, nil),
+ "segment_duration_seconds": utils.PathSearch("segment_duration_seconds", v, nil),
+ "playlist_window_seconds": utils.PathSearch("playlist_window_seconds", v, nil),
+ "encryption": flattenDataEncryptionResponseBody(v),
+ "request_args": flattenDataRequestArgsResponseBody(v),
+ "ad_marker": utils.PathSearch("ad_marker", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataRequestArgsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("request_args", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "record": flattenDataRequestArgsRecordResponseBody(respBody),
+ "timeshift": flattenDataRequestArgsTimeShiftResponseBody(respBody),
+ "live": flattenDataRequestArgsLiveResponseBody(respBody),
+ }}
+}
+
+func flattenDataRequestArgsLiveResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("live", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "delay": utils.PathSearch("delay", v, nil),
+ "unit": utils.PathSearch("unit", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataRequestArgsTimeShiftResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("timeshift", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "back_time": utils.PathSearch("back_time", v, nil),
+ "unit": utils.PathSearch("unit", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataRequestArgsRecordResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("record", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "start_time": utils.PathSearch("start_time", v, nil),
+ "end_time": utils.PathSearch("end_time", v, nil),
+ "format": utils.PathSearch("format", v, nil),
+ "unit": utils.PathSearch("unit", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataStreamSelectionResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("stream_selection", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "key": utils.PathSearch("key", v, nil),
+ "max_bandwidth": utils.PathSearch("max_bandwidth", v, nil),
+ "min_bandwidth": utils.PathSearch("min_bandwidth", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataEncryptionResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("encryption", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "key_rotation_interval_seconds": utils.PathSearch("key_rotation_interval_seconds", respBody, nil),
+ "encryption_method": utils.PathSearch("encryption_method", respBody, nil),
+ "level": utils.PathSearch("level", respBody, nil),
+ "resource_id": utils.PathSearch("resource_id", respBody, nil),
+ "system_ids": utils.PathSearch("system_ids", respBody, nil),
+ "url": utils.PathSearch("url", respBody, nil),
+ "speke_version": utils.PathSearch("speke_version", respBody, nil),
+ "request_mode": utils.PathSearch("request_mode", respBody, nil),
+ "http_headers": flattenDataEncryptionHttpHeadersResponseBody(respBody),
+ "urn": utils.PathSearch("urn", respBody, nil),
+ }}
+}
+
+func flattenDataEncryptionHttpHeadersResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("http_headers", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "key": utils.PathSearch("key", v, nil),
+ "value": utils.PathSearch("value", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataChannelRecordSettingsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("record_settings", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "rollingbuffer_duration": utils.PathSearch("rollingbuffer_duration", respBody, nil),
+ }}
+}
+
+func flattenDataChannelEncoderSettingsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("encoder_settings", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "template_id": utils.PathSearch("template_id", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataChannelInputResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("input", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "input_protocol": utils.PathSearch("input_protocol", respBody, nil),
+ "sources": flattenDataInputSourcesResponseBody(respBody),
+ "secondary_sources": flattenDataInputSecondarySourcesResponseBody(respBody),
+ "failover_conditions": flattenDataInputFailoverConditionsResponseBody(respBody),
+ "max_bandwidth_limit": utils.PathSearch("max_bandwidth_limit", respBody, nil),
+ "ip_port_mode": utils.PathSearch("ip_port_mode", respBody, nil),
+ "ip_whitelist": utils.PathSearch("ip_whitelist", respBody, nil),
+ "scte35_source": utils.PathSearch("scte35_source", respBody, nil),
+ "ad_triggers": utils.PathSearch("ad_triggers", respBody, nil),
+ "audio_selectors": flattenDataInputAudioSelectorsResponseBody(respBody),
+ }}
+}
+
+func flattenDataInputSourcesResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("sources", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "url": utils.PathSearch("url", v, nil),
+ "bitrate": utils.PathSearch("bitrate", v, nil),
+ "width": utils.PathSearch("width", v, nil),
+ "height": utils.PathSearch("height", v, nil),
+ "enable_snapshot": utils.PathSearch("enable_snapshot", v, nil),
+ "bitrate_for3u8": utils.PathSearch("bitrate_for3u8", v, nil),
+ "passphrase": utils.PathSearch("passphrase", v, nil),
+ "backup_urls": utils.PathSearch("backup_urls", v, nil),
+ "stream_id": utils.PathSearch("stream_id", v, nil),
+ "latency": utils.PathSearch("latency", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataInputSecondarySourcesResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("secondary_sources", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "url": utils.PathSearch("url", v, nil),
+ "bitrate": utils.PathSearch("bitrate", v, nil),
+ "width": utils.PathSearch("width", v, nil),
+ "height": utils.PathSearch("height", v, nil),
+ "bitrate_for3u8": utils.PathSearch("bitrate_for3u8", v, nil),
+ "passphrase": utils.PathSearch("passphrase", v, nil),
+ "backup_urls": utils.PathSearch("backup_urls", v, nil),
+ "stream_id": utils.PathSearch("stream_id", v, nil),
+ "latency": utils.PathSearch("latency", v, nil),
+ })
+ }
+ return rst
+}
+
+func flattenDataInputFailoverConditionsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("failover_conditions", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "input_loss_threshold_msec": utils.PathSearch("input_loss_threshold_msec", respBody, nil),
+ "input_preference": utils.PathSearch("input_preference", respBody, nil),
+ }}
+}
+
+func flattenDataInputAudioSelectorsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+ curJson := utils.PathSearch("audio_selectors", resp, make([]interface{}, 0))
+ curArray := curJson.([]interface{})
+ rst := make([]interface{}, 0, len(curArray))
+ for _, v := range curArray {
+ rst = append(rst, map[string]interface{}{
+ "name": utils.PathSearch("name", v, nil),
+ "selector_settings": flattenDataSelectorSettingsResponseBody(v),
+ })
+ }
+ return rst
+}
+
+func flattenDataSelectorSettingsResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("selector_settings", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "audio_language_selection": flattenDataAudioLanguageSelectionResponseBody(respBody),
+ "audio_pid_selection": flattenDataAudioPidSelectionResponseBody(respBody),
+ "audio_hls_selection": flattenDataAudioHlsSelectionResponseBody(respBody),
+ }}
+}
+
+func flattenDataAudioLanguageSelectionResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("audio_language_selection", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "language_code": utils.PathSearch("language_code", respBody, nil),
+ "language_selection_policy": utils.PathSearch("language_selection_policy", respBody, nil),
+ }}
+}
+
+func flattenDataAudioPidSelectionResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("audio_pid_selection", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "pid": utils.PathSearch("pid", respBody, nil),
+ }}
+}
+
+func flattenDataAudioHlsSelectionResponseBody(resp interface{}) []interface{} {
+ if resp == nil {
+ return nil
+ }
+
+ respBody := utils.PathSearch("audio_hls_selection", resp, nil)
+ if respBody == nil {
+ return nil
+ }
+
+ return []interface{}{map[string]interface{}{
+ "name": utils.PathSearch("name", respBody, nil),
+ "group_id": utils.PathSearch("group_id", respBody, nil),
+ }}
+}