package onvif import ( "context" "encoding/xml" "fmt" "github.com/0x524a/onvif-go/internal/soap" ) // Media service namespace. const mediaNamespace = "http://www.onvif.org/ver10/media/wsdl" // getMediaEndpoint returns the media endpoint, falling back to the default endpoint if not set. func (c *Client) getMediaEndpoint() string { if c.mediaEndpoint != "" { return c.mediaEndpoint } return c.endpoint } // getMediaSoapClient creates a new SOAP client for media operations. func (c *Client) getMediaSoapClient() *soap.Client { username, password := c.GetCredentials() return soap.NewClient(c.httpClient, username, password) } // GetProfiles retrieves all media profiles. // //nolint:funlen // GetProfiles has many statements due to parsing complex profile structures func (c *Client) GetProfiles(ctx context.Context) ([]*Profile, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetProfiles struct { XMLName xml.Name `xml:"trt:GetProfiles"` Xmlns string `xml:"xmlns:trt,attr"` } type GetProfilesResponse struct { XMLName xml.Name `xml:"GetProfilesResponse"` Profiles []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` VideoSourceConfiguration *struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` Bounds *struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` } `xml:"Bounds"` } `xml:"VideoSourceConfiguration"` VideoEncoderConfiguration *struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Resolution *struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` Quality float64 `xml:"Quality"` RateControl *struct { FrameRateLimit int `xml:"FrameRateLimit"` EncodingInterval int `xml:"EncodingInterval"` BitrateLimit int `xml:"BitrateLimit"` } `xml:"RateControl"` } `xml:"VideoEncoderConfiguration"` PTZConfiguration *struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` NodeToken string `xml:"NodeToken"` } `xml:"PTZConfiguration"` } `xml:"Profiles"` } req := GetProfiles{ Xmlns: mediaNamespace, } var resp GetProfilesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetProfiles failed: %w", err) } profiles := make([]*Profile, len(resp.Profiles)) for i, p := range resp.Profiles { profile := &Profile{ Token: p.Token, Name: p.Name, } if p.VideoSourceConfiguration != nil { profile.VideoSourceConfiguration = &VideoSourceConfiguration{ Token: p.VideoSourceConfiguration.Token, Name: p.VideoSourceConfiguration.Name, UseCount: p.VideoSourceConfiguration.UseCount, SourceToken: p.VideoSourceConfiguration.SourceToken, } if p.VideoSourceConfiguration.Bounds != nil { profile.VideoSourceConfiguration.Bounds = &IntRectangle{ X: p.VideoSourceConfiguration.Bounds.X, Y: p.VideoSourceConfiguration.Bounds.Y, Width: p.VideoSourceConfiguration.Bounds.Width, Height: p.VideoSourceConfiguration.Bounds.Height, } } } if p.VideoEncoderConfiguration != nil { profile.VideoEncoderConfiguration = &VideoEncoderConfiguration{ Token: p.VideoEncoderConfiguration.Token, Name: p.VideoEncoderConfiguration.Name, UseCount: p.VideoEncoderConfiguration.UseCount, Encoding: p.VideoEncoderConfiguration.Encoding, Quality: p.VideoEncoderConfiguration.Quality, } if p.VideoEncoderConfiguration.Resolution != nil { profile.VideoEncoderConfiguration.Resolution = &VideoResolution{ Width: p.VideoEncoderConfiguration.Resolution.Width, Height: p.VideoEncoderConfiguration.Resolution.Height, } } if p.VideoEncoderConfiguration.RateControl != nil { profile.VideoEncoderConfiguration.RateControl = &VideoRateControl{ FrameRateLimit: p.VideoEncoderConfiguration.RateControl.FrameRateLimit, EncodingInterval: p.VideoEncoderConfiguration.RateControl.EncodingInterval, BitrateLimit: p.VideoEncoderConfiguration.RateControl.BitrateLimit, } } } if p.PTZConfiguration != nil { profile.PTZConfiguration = &PTZConfiguration{ Token: p.PTZConfiguration.Token, Name: p.PTZConfiguration.Name, UseCount: p.PTZConfiguration.UseCount, NodeToken: p.PTZConfiguration.NodeToken, } } profiles[i] = profile } return profiles, nil } // GetStreamURI retrieves the stream URI for a profile. func (c *Client) GetStreamURI(ctx context.Context, profileToken string) (*MediaURI, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetStreamURI struct { XMLName xml.Name `xml:"trt:GetStreamUri"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` StreamSetup struct { Stream string `xml:"tt:Stream"` Transport struct { Protocol string `xml:"tt:Protocol"` } `xml:"tt:Transport"` } `xml:"trt:StreamSetup"` ProfileToken string `xml:"trt:ProfileToken"` } type GetStreamURIResponse struct { XMLName xml.Name `xml:"GetStreamUriResponse"` MediaURI struct { URI string `xml:"Uri"` InvalidAfterConnect bool `xml:"InvalidAfterConnect"` InvalidAfterReboot bool `xml:"InvalidAfterReboot"` Timeout string `xml:"Timeout"` } `xml:"MediaUri"` } req := GetStreamURI{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ProfileToken: profileToken, } req.StreamSetup.Stream = "RTP-Unicast" req.StreamSetup.Transport.Protocol = "RTSP" var resp GetStreamURIResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetStreamURI failed: %w", err) } return &MediaURI{ URI: resp.MediaURI.URI, InvalidAfterConnect: resp.MediaURI.InvalidAfterConnect, InvalidAfterReboot: resp.MediaURI.InvalidAfterReboot, }, nil } // GetSnapshotURI retrieves the snapshot URI for a profile. func (c *Client) GetSnapshotURI(ctx context.Context, profileToken string) (*MediaURI, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetSnapshotURI struct { XMLName xml.Name `xml:"trt:GetSnapshotUri"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetSnapshotURIResponse struct { XMLName xml.Name `xml:"GetSnapshotUriResponse"` MediaURI struct { URI string `xml:"Uri"` InvalidAfterConnect bool `xml:"InvalidAfterConnect"` InvalidAfterReboot bool `xml:"InvalidAfterReboot"` Timeout string `xml:"Timeout"` } `xml:"MediaUri"` } req := GetSnapshotURI{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetSnapshotURIResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetSnapshotURI failed: %w", err) } return &MediaURI{ URI: resp.MediaURI.URI, InvalidAfterConnect: resp.MediaURI.InvalidAfterConnect, InvalidAfterReboot: resp.MediaURI.InvalidAfterReboot, }, nil } // GetVideoEncoderConfiguration retrieves video encoder configuration. func (c *Client) GetVideoEncoderConfiguration( ctx context.Context, configurationToken string, ) (*VideoEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoEncoderConfiguration struct { XMLName xml.Name `xml:"trt:GetVideoEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetVideoEncoderConfigurationResponse struct { XMLName xml.Name `xml:"GetVideoEncoderConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Resolution *struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` Quality float64 `xml:"Quality"` RateControl *struct { FrameRateLimit int `xml:"FrameRateLimit"` EncodingInterval int `xml:"EncodingInterval"` BitrateLimit int `xml:"BitrateLimit"` } `xml:"RateControl"` } `xml:"Configuration"` } req := GetVideoEncoderConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetVideoEncoderConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoEncoderConfiguration failed: %w", err) } config := &VideoEncoderConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, Encoding: resp.Configuration.Encoding, Quality: resp.Configuration.Quality, } if resp.Configuration.Resolution != nil { config.Resolution = &VideoResolution{ Width: resp.Configuration.Resolution.Width, Height: resp.Configuration.Resolution.Height, } } if resp.Configuration.RateControl != nil { config.RateControl = &VideoRateControl{ FrameRateLimit: resp.Configuration.RateControl.FrameRateLimit, EncodingInterval: resp.Configuration.RateControl.EncodingInterval, BitrateLimit: resp.Configuration.RateControl.BitrateLimit, } } return config, nil } // GetVideoSources retrieves all video sources. func (c *Client) GetVideoSources(ctx context.Context) ([]*VideoSource, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoSources struct { XMLName xml.Name `xml:"trt:GetVideoSources"` Xmlns string `xml:"xmlns:trt,attr"` } type GetVideoSourcesResponse struct { XMLName xml.Name `xml:"GetVideoSourcesResponse"` VideoSources []struct { Token string `xml:"token,attr"` Framerate float64 `xml:"Framerate"` Resolution struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` } `xml:"VideoSources"` } req := GetVideoSources{ Xmlns: mediaNamespace, } var resp GetVideoSourcesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoSources failed: %w", err) } sources := make([]*VideoSource, len(resp.VideoSources)) for i, s := range resp.VideoSources { sources[i] = &VideoSource{ Token: s.Token, Framerate: s.Framerate, Resolution: &VideoResolution{ Width: s.Resolution.Width, Height: s.Resolution.Height, }, } } return sources, nil } // GetAudioSources retrieves all audio sources. func (c *Client) GetAudioSources(ctx context.Context) ([]*AudioSource, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioSources struct { XMLName xml.Name `xml:"trt:GetAudioSources"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioSourcesResponse struct { XMLName xml.Name `xml:"GetAudioSourcesResponse"` AudioSources []struct { Token string `xml:"token,attr"` Channels int `xml:"Channels"` } `xml:"AudioSources"` } req := GetAudioSources{ Xmlns: mediaNamespace, } var resp GetAudioSourcesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioSources failed: %w", err) } sources := make([]*AudioSource, len(resp.AudioSources)) for i, s := range resp.AudioSources { sources[i] = &AudioSource{ Token: s.Token, Channels: s.Channels, } } return sources, nil } // GetAudioOutputs retrieves all audio outputs. func (c *Client) GetAudioOutputs(ctx context.Context) ([]*AudioOutput, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioOutputs struct { XMLName xml.Name `xml:"trt:GetAudioOutputs"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioOutputsResponse struct { XMLName xml.Name `xml:"GetAudioOutputsResponse"` AudioOutputs []struct { Token string `xml:"token,attr"` } `xml:"AudioOutputs"` } req := GetAudioOutputs{ Xmlns: mediaNamespace, } var resp GetAudioOutputsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioOutputs failed: %w", err) } outputs := make([]*AudioOutput, len(resp.AudioOutputs)) for i, o := range resp.AudioOutputs { outputs[i] = &AudioOutput{ Token: o.Token, } } return outputs, nil } // CreateProfile creates a new media profile. func (c *Client) CreateProfile(ctx context.Context, name, token string) (*Profile, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type CreateProfile struct { XMLName xml.Name `xml:"trt:CreateProfile"` Xmlns string `xml:"xmlns:trt,attr"` Name string `xml:"trt:Name"` Token *string `xml:"trt:Token,omitempty"` } type CreateProfileResponse struct { XMLName xml.Name `xml:"CreateProfileResponse"` Profile struct { Token string `xml:"token,attr"` Name string `xml:"Name"` } `xml:"Profile"` } req := CreateProfile{ Xmlns: mediaNamespace, Name: name, } if token != "" { req.Token = &token } var resp CreateProfileResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("CreateProfile failed: %w", err) } return &Profile{ Token: resp.Profile.Token, Name: resp.Profile.Name, }, nil } // DeleteProfile deletes a media profile. func (c *Client) DeleteProfile(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type DeleteProfile struct { XMLName xml.Name `xml:"trt:DeleteProfile"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := DeleteProfile{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("DeleteProfile failed: %w", err) } return nil } // SetVideoEncoderConfiguration sets video encoder configuration. func (c *Client) SetVideoEncoderConfiguration( ctx context.Context, config *VideoEncoderConfiguration, forcePersistence bool, ) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetVideoEncoderConfiguration struct { XMLName xml.Name `xml:"trt:SetVideoEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` Encoding string `xml:"tt:Encoding"` Resolution *struct { Width int `xml:"tt:Width"` Height int `xml:"tt:Height"` } `xml:"tt:Resolution,omitempty"` Quality *float64 `xml:"tt:Quality,omitempty"` RateControl *struct { FrameRateLimit int `xml:"tt:FrameRateLimit"` EncodingInterval int `xml:"tt:EncodingInterval"` BitrateLimit int `xml:"tt:BitrateLimit"` } `xml:"tt:RateControl,omitempty"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetVideoEncoderConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.Encoding = config.Encoding if config.Resolution != nil { req.Configuration.Resolution = &struct { Width int `xml:"tt:Width"` Height int `xml:"tt:Height"` }{ Width: config.Resolution.Width, Height: config.Resolution.Height, } } if config.Quality > 0 { req.Configuration.Quality = &config.Quality } if config.RateControl != nil { req.Configuration.RateControl = &struct { FrameRateLimit int `xml:"tt:FrameRateLimit"` EncodingInterval int `xml:"tt:EncodingInterval"` BitrateLimit int `xml:"tt:BitrateLimit"` }{ FrameRateLimit: config.RateControl.FrameRateLimit, EncodingInterval: config.RateControl.EncodingInterval, BitrateLimit: config.RateControl.BitrateLimit, } } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetVideoEncoderConfiguration failed: %w", err) } return nil } // GetMediaServiceCapabilities retrieves media service capabilities. func (c *Client) GetMediaServiceCapabilities(ctx context.Context) (*MediaServiceCapabilities, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetServiceCapabilities struct { XMLName xml.Name `xml:"trt:GetServiceCapabilities"` Xmlns string `xml:"xmlns:trt,attr"` } type GetServiceCapabilitiesResponse struct { XMLName xml.Name `xml:"GetServiceCapabilitiesResponse"` Capabilities struct { SnapshotURI bool `xml:"SnapshotUri,attr"` Rotation bool `xml:"Rotation,attr"` VideoSourceMode bool `xml:"VideoSourceMode,attr"` OSD bool `xml:"OSD,attr"` TemporaryOSDText bool `xml:"TemporaryOSDText,attr"` EXICompression bool `xml:"EXICompression,attr"` ProfileCapabilities *struct { MaximumNumberOfProfiles int `xml:"MaximumNumberOfProfiles,attr"` } `xml:"ProfileCapabilities"` StreamingCapabilities *struct { RTPMulticast bool `xml:"RTPMulticast,attr"` RTPTCP bool `xml:"RTP_TCP,attr"` RTPRTSPTCP bool `xml:"RTP_RTSP_TCP,attr"` } `xml:"StreamingCapabilities"` } `xml:"Capabilities"` } req := GetServiceCapabilities{ Xmlns: mediaNamespace, } var resp GetServiceCapabilitiesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetMediaServiceCapabilities failed: %w", err) } caps := &MediaServiceCapabilities{ SnapshotURI: resp.Capabilities.SnapshotURI, Rotation: resp.Capabilities.Rotation, VideoSourceMode: resp.Capabilities.VideoSourceMode, OSD: resp.Capabilities.OSD, TemporaryOSDText: resp.Capabilities.TemporaryOSDText, EXICompression: resp.Capabilities.EXICompression, } if resp.Capabilities.ProfileCapabilities != nil { caps.MaximumNumberOfProfiles = resp.Capabilities.ProfileCapabilities.MaximumNumberOfProfiles } if resp.Capabilities.StreamingCapabilities != nil { caps.RTPMulticast = resp.Capabilities.StreamingCapabilities.RTPMulticast caps.RTPTCP = resp.Capabilities.StreamingCapabilities.RTPTCP caps.RTPRTSPTCP = resp.Capabilities.StreamingCapabilities.RTPRTSPTCP } return caps, nil } // GetVideoEncoderConfigurationOptions retrieves available options for video encoder configuration. // //nolint:funlen // GetVideoEncoderConfigurationOptions has many statements due to parsing complex encoder options func (c *Client) GetVideoEncoderConfigurationOptions( ctx context.Context, configurationToken string, ) (*VideoEncoderConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoEncoderConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetVideoEncoderConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetVideoEncoderConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetVideoEncoderConfigurationOptionsResponse"` Options struct { QualityRange *struct { Min float64 `xml:"Min"` Max float64 `xml:"Max"` } `xml:"QualityRange"` JPEG *struct { ResolutionsAvailable []struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"ResolutionsAvailable"` FrameRateRange *struct { Min float64 `xml:"Min"` Max float64 `xml:"Max"` } `xml:"FrameRateRange"` EncodingIntervalRange *struct { Min int `xml:"Min"` Max int `xml:"Max"` } `xml:"EncodingIntervalRange"` } `xml:"JPEG"` H264 *struct { ResolutionsAvailable []struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"ResolutionsAvailable"` GovLengthRange *struct { Min int `xml:"Min"` Max int `xml:"Max"` } `xml:"GovLengthRange"` FrameRateRange *struct { Min float64 `xml:"Min"` Max float64 `xml:"Max"` } `xml:"FrameRateRange"` EncodingIntervalRange *struct { Min int `xml:"Min"` Max int `xml:"Max"` } `xml:"EncodingIntervalRange"` H264ProfilesSupported []string `xml:"H264ProfilesSupported"` } `xml:"H264"` Extension struct{} `xml:"Extension"` } `xml:"Options"` } req := GetVideoEncoderConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } var resp GetVideoEncoderConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoEncoderConfigurationOptions failed: %w", err) } options := &VideoEncoderConfigurationOptions{} if resp.Options.QualityRange != nil { options.QualityRange = &FloatRange{ Min: resp.Options.QualityRange.Min, Max: resp.Options.QualityRange.Max, } } if resp.Options.JPEG != nil { jpegOpts := &JPEGOptions{} if resp.Options.JPEG.FrameRateRange != nil { jpegOpts.FrameRateRange = &FloatRange{ Min: resp.Options.JPEG.FrameRateRange.Min, Max: resp.Options.JPEG.FrameRateRange.Max, } } if resp.Options.JPEG.EncodingIntervalRange != nil { jpegOpts.EncodingIntervalRange = &IntRange{ Min: resp.Options.JPEG.EncodingIntervalRange.Min, Max: resp.Options.JPEG.EncodingIntervalRange.Max, } } for _, res := range resp.Options.JPEG.ResolutionsAvailable { jpegOpts.ResolutionsAvailable = append(jpegOpts.ResolutionsAvailable, &VideoResolution{ Width: res.Width, Height: res.Height, }) } options.JPEG = jpegOpts } if resp.Options.H264 != nil { h264Opts := &H264Options{} if resp.Options.H264.FrameRateRange != nil { h264Opts.FrameRateRange = &FloatRange{ Min: resp.Options.H264.FrameRateRange.Min, Max: resp.Options.H264.FrameRateRange.Max, } } if resp.Options.H264.GovLengthRange != nil { h264Opts.GovLengthRange = &IntRange{ Min: resp.Options.H264.GovLengthRange.Min, Max: resp.Options.H264.GovLengthRange.Max, } } if resp.Options.H264.EncodingIntervalRange != nil { h264Opts.EncodingIntervalRange = &IntRange{ Min: resp.Options.H264.EncodingIntervalRange.Min, Max: resp.Options.H264.EncodingIntervalRange.Max, } } for _, res := range resp.Options.H264.ResolutionsAvailable { h264Opts.ResolutionsAvailable = append(h264Opts.ResolutionsAvailable, &VideoResolution{ Width: res.Width, Height: res.Height, }) } h264Opts.H264ProfilesSupported = resp.Options.H264.H264ProfilesSupported options.H264 = h264Opts } return options, nil } // GetAudioEncoderConfiguration retrieves audio encoder configuration. func (c *Client) GetAudioEncoderConfiguration( ctx context.Context, configurationToken string, ) (*AudioEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioEncoderConfiguration struct { XMLName xml.Name `xml:"trt:GetAudioEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetAudioEncoderConfigurationResponse struct { XMLName xml.Name `xml:"GetAudioEncoderConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Bitrate int `xml:"Bitrate"` SampleRate int `xml:"SampleRate"` Multicast *struct { Address *struct { Type string `xml:"Type"` IPv4Address string `xml:"IPv4Address"` IPv6Address string `xml:"IPv6Address"` } `xml:"Address"` Port int `xml:"Port"` TTL int `xml:"TTL"` AutoStart bool `xml:"AutoStart"` } `xml:"Multicast"` SessionTimeout string `xml:"SessionTimeout"` } `xml:"Configuration"` } req := GetAudioEncoderConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetAudioEncoderConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioEncoderConfiguration failed: %w", err) } config := &AudioEncoderConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, Encoding: resp.Configuration.Encoding, Bitrate: resp.Configuration.Bitrate, SampleRate: resp.Configuration.SampleRate, } if resp.Configuration.Multicast != nil { config.Multicast = &MulticastConfiguration{ Port: resp.Configuration.Multicast.Port, TTL: resp.Configuration.Multicast.TTL, AutoStart: resp.Configuration.Multicast.AutoStart, } if resp.Configuration.Multicast.Address != nil { config.Multicast.Address = &IPAddress{ Type: resp.Configuration.Multicast.Address.Type, IPv4Address: resp.Configuration.Multicast.Address.IPv4Address, IPv6Address: resp.Configuration.Multicast.Address.IPv6Address, } } } return config, nil } // SetAudioEncoderConfiguration sets audio encoder configuration. func (c *Client) SetAudioEncoderConfiguration( ctx context.Context, config *AudioEncoderConfiguration, forcePersistence bool, ) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetAudioEncoderConfiguration struct { XMLName xml.Name `xml:"trt:SetAudioEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` Encoding string `xml:"tt:Encoding"` Bitrate int `xml:"tt:Bitrate,omitempty"` SampleRate int `xml:"tt:SampleRate,omitempty"` Multicast *struct { Address *struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` } `xml:"tt:Address,omitempty"` Port int `xml:"tt:Port,omitempty"` TTL int `xml:"tt:TTL,omitempty"` AutoStart bool `xml:"tt:AutoStart,omitempty"` } `xml:"tt:Multicast,omitempty"` SessionTimeout string `xml:"tt:SessionTimeout,omitempty"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetAudioEncoderConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.Encoding = config.Encoding if config.Bitrate > 0 { req.Configuration.Bitrate = config.Bitrate } if config.SampleRate > 0 { req.Configuration.SampleRate = config.SampleRate } if config.Multicast != nil { req.Configuration.Multicast = &struct { Address *struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` } `xml:"tt:Address,omitempty"` Port int `xml:"tt:Port,omitempty"` TTL int `xml:"tt:TTL,omitempty"` AutoStart bool `xml:"tt:AutoStart,omitempty"` }{ Port: config.Multicast.Port, TTL: config.Multicast.TTL, AutoStart: config.Multicast.AutoStart, } if config.Multicast.Address != nil { req.Configuration.Multicast.Address = &struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` }{ Type: config.Multicast.Address.Type, IPv4Address: config.Multicast.Address.IPv4Address, IPv6Address: config.Multicast.Address.IPv6Address, } } } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetAudioEncoderConfiguration failed: %w", err) } return nil } // GetMetadataConfiguration retrieves metadata configuration. func (c *Client) GetMetadataConfiguration( ctx context.Context, configurationToken string, ) (*MetadataConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetMetadataConfiguration struct { XMLName xml.Name `xml:"trt:GetMetadataConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetMetadataConfigurationResponse struct { XMLName xml.Name `xml:"GetMetadataConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` PTZStatus *struct { Status bool `xml:"Status"` Position bool `xml:"Position"` } `xml:"PTZStatus"` Events *struct{} `xml:"Events"` Analytics bool `xml:"Analytics"` Multicast *struct { Address *struct { Type string `xml:"Type"` IPv4Address string `xml:"IPv4Address"` IPv6Address string `xml:"IPv6Address"` } `xml:"Address"` Port int `xml:"Port"` TTL int `xml:"TTL"` AutoStart bool `xml:"AutoStart"` } `xml:"Multicast"` SessionTimeout string `xml:"SessionTimeout"` } `xml:"Configuration"` } req := GetMetadataConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetMetadataConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetMetadataConfiguration failed: %w", err) } config := &MetadataConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, Analytics: resp.Configuration.Analytics, } if resp.Configuration.PTZStatus != nil { config.PTZStatus = &PTZFilter{ Status: resp.Configuration.PTZStatus.Status, Position: resp.Configuration.PTZStatus.Position, } } if resp.Configuration.Events != nil { config.Events = &EventSubscription{} } if resp.Configuration.Multicast != nil { config.Multicast = &MulticastConfiguration{ Port: resp.Configuration.Multicast.Port, TTL: resp.Configuration.Multicast.TTL, AutoStart: resp.Configuration.Multicast.AutoStart, } if resp.Configuration.Multicast.Address != nil { config.Multicast.Address = &IPAddress{ Type: resp.Configuration.Multicast.Address.Type, IPv4Address: resp.Configuration.Multicast.Address.IPv4Address, IPv6Address: resp.Configuration.Multicast.Address.IPv6Address, } } } return config, nil } // SetMetadataConfiguration sets metadata configuration. func (c *Client) SetMetadataConfiguration( ctx context.Context, config *MetadataConfiguration, forcePersistence bool, ) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetMetadataConfiguration struct { XMLName xml.Name `xml:"trt:SetMetadataConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` PTZStatus *struct { Status bool `xml:"tt:Status"` Position bool `xml:"tt:Position"` } `xml:"tt:PTZStatus,omitempty"` Events *struct{} `xml:"tt:Events,omitempty"` Analytics bool `xml:"tt:Analytics,omitempty"` Multicast *struct { Address *struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` } `xml:"tt:Address,omitempty"` Port int `xml:"tt:Port,omitempty"` TTL int `xml:"tt:TTL,omitempty"` AutoStart bool `xml:"tt:AutoStart,omitempty"` } `xml:"tt:Multicast,omitempty"` SessionTimeout string `xml:"tt:SessionTimeout,omitempty"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetMetadataConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.Analytics = config.Analytics if config.PTZStatus != nil { req.Configuration.PTZStatus = &struct { Status bool `xml:"tt:Status"` Position bool `xml:"tt:Position"` }{ Status: config.PTZStatus.Status, Position: config.PTZStatus.Position, } } if config.Events != nil { req.Configuration.Events = &struct{}{} } if config.Multicast != nil { req.Configuration.Multicast = &struct { Address *struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` } `xml:"tt:Address,omitempty"` Port int `xml:"tt:Port,omitempty"` TTL int `xml:"tt:TTL,omitempty"` AutoStart bool `xml:"tt:AutoStart,omitempty"` }{ Port: config.Multicast.Port, TTL: config.Multicast.TTL, AutoStart: config.Multicast.AutoStart, } if config.Multicast.Address != nil { req.Configuration.Multicast.Address = &struct { Type string `xml:"tt:Type"` IPv4Address string `xml:"tt:IPv4Address,omitempty"` IPv6Address string `xml:"tt:IPv6Address,omitempty"` }{ Type: config.Multicast.Address.Type, IPv4Address: config.Multicast.Address.IPv4Address, IPv6Address: config.Multicast.Address.IPv6Address, } } } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetMetadataConfiguration failed: %w", err) } return nil } // GetVideoSourceModes retrieves available video source modes. func (c *Client) GetVideoSourceModes(ctx context.Context, videoSourceToken string) ([]*VideoSourceMode, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoSourceModes struct { XMLName xml.Name `xml:"trt:GetVideoSourceModes"` Xmlns string `xml:"xmlns:trt,attr"` VideoSourceToken string `xml:"trt:VideoSourceToken"` } type GetVideoSourceModesResponse struct { XMLName xml.Name `xml:"GetVideoSourceModesResponse"` VideoSourceModes []struct { Token string `xml:"token,attr"` Enabled bool `xml:"Enabled"` Resolution struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` } `xml:"VideoSourceModes"` } req := GetVideoSourceModes{ Xmlns: mediaNamespace, VideoSourceToken: videoSourceToken, } var resp GetVideoSourceModesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoSourceModes failed: %w", err) } modes := make([]*VideoSourceMode, len(resp.VideoSourceModes)) for i, m := range resp.VideoSourceModes { modes[i] = &VideoSourceMode{ Token: m.Token, Enabled: m.Enabled, Resolution: &VideoResolution{ Width: m.Resolution.Width, Height: m.Resolution.Height, }, } } return modes, nil } // SetVideoSourceMode sets the video source mode. func (c *Client) SetVideoSourceMode(ctx context.Context, videoSourceToken, modeToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetVideoSourceMode struct { XMLName xml.Name `xml:"trt:SetVideoSourceMode"` Xmlns string `xml:"xmlns:trt,attr"` VideoSourceToken string `xml:"trt:VideoSourceToken"` ModeToken string `xml:"trt:ModeToken"` } req := SetVideoSourceMode{ Xmlns: mediaNamespace, VideoSourceToken: videoSourceToken, ModeToken: modeToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetVideoSourceMode failed: %w", err) } return nil } // SetSynchronizationPoint sets a synchronization point for the stream. func (c *Client) SetSynchronizationPoint(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetSynchronizationPoint struct { XMLName xml.Name `xml:"trt:SetSynchronizationPoint"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := SetSynchronizationPoint{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetSynchronizationPoint failed: %w", err) } return nil } // GetOSDs retrieves all OSD configurations. func (c *Client) GetOSDs(ctx context.Context, configurationToken string) ([]*OSDConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetOSDs struct { XMLName xml.Name `xml:"trt:GetOSDs"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` } type GetOSDsResponse struct { XMLName xml.Name `xml:"GetOSDsResponse"` OSDs []struct { Token string `xml:"token,attr"` } `xml:"OSDs"` } req := GetOSDs{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } var resp GetOSDsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetOSDs failed: %w", err) } osds := make([]*OSDConfiguration, len(resp.OSDs)) for i, o := range resp.OSDs { osds[i] = &OSDConfiguration{ Token: o.Token, } } return osds, nil } // GetOSD retrieves a specific OSD configuration. func (c *Client) GetOSD(ctx context.Context, osdToken string) (*OSDConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetOSD struct { XMLName xml.Name `xml:"trt:GetOSD"` Xmlns string `xml:"xmlns:trt,attr"` OSDToken string `xml:"trt:OSDToken"` } type GetOSDResponse struct { XMLName xml.Name `xml:"GetOSDResponse"` OSD struct { Token string `xml:"token,attr"` } `xml:"OSD"` } req := GetOSD{ Xmlns: mediaNamespace, OSDToken: osdToken, } var resp GetOSDResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetOSD failed: %w", err) } return &OSDConfiguration{ Token: resp.OSD.Token, }, nil } // SetOSD sets OSD configuration. func (c *Client) SetOSD(ctx context.Context, osd *OSDConfiguration) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetOSD struct { XMLName xml.Name `xml:"trt:SetOSD"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` OSD struct { Token string `xml:"token,attr"` } `xml:"trt:OSD"` } req := SetOSD{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", } req.OSD.Token = osd.Token username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetOSD failed: %w", err) } return nil } // CreateOSD creates a new OSD configuration. func (c *Client) CreateOSD( ctx context.Context, videoSourceConfigurationToken string, osd *OSDConfiguration, ) (*OSDConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type CreateOSD struct { XMLName xml.Name `xml:"trt:CreateOSD"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` VideoSourceConfigurationToken string `xml:"trt:VideoSourceConfigurationToken"` OSD struct { Token string `xml:"token,attr,omitempty"` } `xml:"trt:OSD"` } type CreateOSDResponse struct { XMLName xml.Name `xml:"CreateOSDResponse"` OSD struct { Token string `xml:"token,attr"` } `xml:"OSD"` } req := CreateOSD{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", VideoSourceConfigurationToken: videoSourceConfigurationToken, } if osd != nil && osd.Token != "" { req.OSD.Token = osd.Token } var resp CreateOSDResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("CreateOSD failed: %w", err) } return &OSDConfiguration{ Token: resp.OSD.Token, }, nil } // DeleteOSD deletes an OSD configuration. func (c *Client) DeleteOSD(ctx context.Context, osdToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type DeleteOSD struct { XMLName xml.Name `xml:"trt:DeleteOSD"` Xmlns string `xml:"xmlns:trt,attr"` OSDToken string `xml:"trt:OSDToken"` } req := DeleteOSD{ Xmlns: mediaNamespace, OSDToken: osdToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("DeleteOSD failed: %w", err) } return nil } // StartMulticastStreaming starts multicast streaming. func (c *Client) StartMulticastStreaming(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type StartMulticastStreaming struct { XMLName xml.Name `xml:"trt:StartMulticastStreaming"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := StartMulticastStreaming{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("StartMulticastStreaming failed: %w", err) } return nil } // StopMulticastStreaming stops multicast streaming. func (c *Client) StopMulticastStreaming(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type StopMulticastStreaming struct { XMLName xml.Name `xml:"trt:StopMulticastStreaming"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := StopMulticastStreaming{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("StopMulticastStreaming failed: %w", err) } return nil } // GetProfile retrieves a specific media profile. func (c *Client) GetProfile(ctx context.Context, profileToken string) (*Profile, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetProfile struct { XMLName xml.Name `xml:"trt:GetProfile"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetProfileResponse struct { XMLName xml.Name `xml:"GetProfileResponse"` Profile struct { Token string `xml:"token,attr"` Name string `xml:"Name"` } `xml:"Profile"` } req := GetProfile{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetProfileResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetProfile failed: %w", err) } return &Profile{ Token: resp.Profile.Token, Name: resp.Profile.Name, }, nil } // SetProfile sets profile configuration. func (c *Client) SetProfile(ctx context.Context, profile *Profile) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetProfile struct { XMLName xml.Name `xml:"trt:SetProfile"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Profile struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` } `xml:"trt:Profile"` } req := SetProfile{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", } req.Profile.Token = profile.Token req.Profile.Name = profile.Name username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetProfile failed: %w", err) } return nil } // AddVideoEncoderConfiguration adds video encoder configuration to a profile. func (c *Client) AddVideoEncoderConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddVideoEncoderConfiguration struct { XMLName xml.Name `xml:"trt:AddVideoEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddVideoEncoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddVideoEncoderConfiguration failed: %w", err) } return nil } // RemoveVideoEncoderConfiguration removes video encoder configuration from a profile. func (c *Client) RemoveVideoEncoderConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveVideoEncoderConfiguration struct { XMLName xml.Name `xml:"trt:RemoveVideoEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveVideoEncoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveVideoEncoderConfiguration failed: %w", err) } return nil } // AddAudioEncoderConfiguration adds audio encoder configuration to a profile. func (c *Client) AddAudioEncoderConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddAudioEncoderConfiguration struct { XMLName xml.Name `xml:"trt:AddAudioEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddAudioEncoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddAudioEncoderConfiguration failed: %w", err) } return nil } // RemoveAudioEncoderConfiguration removes audio encoder configuration from a profile. func (c *Client) RemoveAudioEncoderConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveAudioEncoderConfiguration struct { XMLName xml.Name `xml:"trt:RemoveAudioEncoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveAudioEncoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveAudioEncoderConfiguration failed: %w", err) } return nil } // AddAudioSourceConfiguration adds audio source configuration to a profile. func (c *Client) AddAudioSourceConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddAudioSourceConfiguration struct { XMLName xml.Name `xml:"trt:AddAudioSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddAudioSourceConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddAudioSourceConfiguration failed: %w", err) } return nil } // RemoveAudioSourceConfiguration removes audio source configuration from a profile. func (c *Client) RemoveAudioSourceConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveAudioSourceConfiguration struct { XMLName xml.Name `xml:"trt:RemoveAudioSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveAudioSourceConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveAudioSourceConfiguration failed: %w", err) } return nil } // AddVideoSourceConfiguration adds video source configuration to a profile. func (c *Client) AddVideoSourceConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddVideoSourceConfiguration struct { XMLName xml.Name `xml:"trt:AddVideoSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddVideoSourceConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddVideoSourceConfiguration failed: %w", err) } return nil } // RemoveVideoSourceConfiguration removes video source configuration from a profile. func (c *Client) RemoveVideoSourceConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveVideoSourceConfiguration struct { XMLName xml.Name `xml:"trt:RemoveVideoSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveVideoSourceConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveVideoSourceConfiguration failed: %w", err) } return nil } // AddPTZConfiguration adds PTZ configuration to a profile. func (c *Client) AddPTZConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddPTZConfiguration struct { XMLName xml.Name `xml:"trt:AddPTZConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddPTZConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddPTZConfiguration failed: %w", err) } return nil } // RemovePTZConfiguration removes PTZ configuration from a profile. func (c *Client) RemovePTZConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemovePTZConfiguration struct { XMLName xml.Name `xml:"trt:RemovePTZConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemovePTZConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemovePTZConfiguration failed: %w", err) } return nil } // AddMetadataConfiguration adds metadata configuration to a profile. func (c *Client) AddMetadataConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddMetadataConfiguration struct { XMLName xml.Name `xml:"trt:AddMetadataConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddMetadataConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddMetadataConfiguration failed: %w", err) } return nil } // RemoveMetadataConfiguration removes metadata configuration from a profile. func (c *Client) RemoveMetadataConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveMetadataConfiguration struct { XMLName xml.Name `xml:"trt:RemoveMetadataConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveMetadataConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveMetadataConfiguration failed: %w", err) } return nil } // GetAudioEncoderConfigurationOptions retrieves available options for audio encoder configuration. func (c *Client) GetAudioEncoderConfigurationOptions( ctx context.Context, configurationToken, profileToken string, ) (*AudioEncoderConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioEncoderConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetAudioEncoderConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetAudioEncoderConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetAudioEncoderConfigurationOptionsResponse"` Options struct { EncodingOptions []string `xml:"EncodingOptions"` BitrateList []int `xml:"BitrateList"` SampleRateList []int `xml:"SampleRateList"` } `xml:"Options"` } req := GetAudioEncoderConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } if profileToken != "" { req.ProfileToken = profileToken } var resp GetAudioEncoderConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioEncoderConfigurationOptions failed: %w", err) } return &AudioEncoderConfigurationOptions{ EncodingOptions: resp.Options.EncodingOptions, BitrateList: resp.Options.BitrateList, SampleRateList: resp.Options.SampleRateList, }, nil } // GetMetadataConfigurationOptions retrieves available options for metadata configuration. func (c *Client) GetMetadataConfigurationOptions( ctx context.Context, configurationToken, profileToken string, ) (*MetadataConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetMetadataConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetMetadataConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetMetadataConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetMetadataConfigurationOptionsResponse"` Options struct { PTZStatusFilterOptions *struct { Status bool `xml:"Status"` Position bool `xml:"Position"` } `xml:"PTZStatusFilterOptions"` Extension struct{} `xml:"Extension"` } `xml:"Options"` } req := GetMetadataConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } if profileToken != "" { req.ProfileToken = profileToken } var resp GetMetadataConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetMetadataConfigurationOptions failed: %w", err) } options := &MetadataConfigurationOptions{} if resp.Options.PTZStatusFilterOptions != nil { options.PTZStatusFilterOptions = &PTZFilter{ Status: resp.Options.PTZStatusFilterOptions.Status, Position: resp.Options.PTZStatusFilterOptions.Position, } } return options, nil } // GetAudioOutputConfiguration retrieves audio output configuration. func (c *Client) GetAudioOutputConfiguration(ctx context.Context, configurationToken string) (*AudioOutputConfiguration, error) { endpoint := c.getMediaEndpoint() type GetAudioOutputConfiguration struct { XMLName xml.Name `xml:"trt:GetAudioOutputConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetAudioOutputConfigurationResponse struct { XMLName xml.Name `xml:"GetAudioOutputConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` OutputToken string `xml:"OutputToken"` } `xml:"Configuration"` } req := GetAudioOutputConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetAudioOutputConfigurationResponse soapClient := c.getMediaSoapClient() if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioOutputConfiguration failed: %w", err) } return &AudioOutputConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, OutputToken: resp.Configuration.OutputToken, }, nil } // SetAudioOutputConfiguration sets audio output configuration. func (c *Client) SetAudioOutputConfiguration(ctx context.Context, config *AudioOutputConfiguration, forcePersistence bool) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetAudioOutputConfiguration struct { XMLName xml.Name `xml:"trt:SetAudioOutputConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` OutputToken string `xml:"tt:OutputToken"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetAudioOutputConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.OutputToken = config.OutputToken username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetAudioOutputConfiguration failed: %w", err) } return nil } // GetAudioOutputConfigurationOptions retrieves available options for audio output configuration. func (c *Client) GetAudioOutputConfigurationOptions( ctx context.Context, configurationToken string, ) (*AudioOutputConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioOutputConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetAudioOutputConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` } type GetAudioOutputConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetAudioOutputConfigurationOptionsResponse"` Options struct { OutputTokensAvailable []string `xml:"OutputTokensAvailable"` } `xml:"Options"` } req := GetAudioOutputConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } var resp GetAudioOutputConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioOutputConfigurationOptions failed: %w", err) } return &AudioOutputConfigurationOptions{ OutputTokensAvailable: resp.Options.OutputTokensAvailable, }, nil } // GetAudioDecoderConfigurationOptions retrieves available options for audio decoder configuration. func (c *Client) GetAudioDecoderConfigurationOptions( ctx context.Context, configurationToken string, ) (*AudioDecoderConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioDecoderConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetAudioDecoderConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` } type GetAudioDecoderConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetAudioDecoderConfigurationOptionsResponse"` Options struct { AACDecOptions *struct { BitrateList []int `xml:"BitrateList"` SampleRateList []int `xml:"SampleRateList"` } `xml:"AACDecOptions"` G711DecOptions *struct { BitrateList []int `xml:"BitrateList"` } `xml:"G711DecOptions"` G726DecOptions *struct { BitrateList []int `xml:"BitrateList"` } `xml:"G726DecOptions"` } `xml:"Options"` } req := GetAudioDecoderConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } var resp GetAudioDecoderConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioDecoderConfigurationOptions failed: %w", err) } options := &AudioDecoderConfigurationOptions{} if resp.Options.AACDecOptions != nil { options.AACDecOptions = &AudioDecoderOptions{ BitrateList: resp.Options.AACDecOptions.BitrateList, SampleRateList: resp.Options.AACDecOptions.SampleRateList, } } if resp.Options.G711DecOptions != nil { options.G711DecOptions = &AudioDecoderOptions{ BitrateList: resp.Options.G711DecOptions.BitrateList, } } if resp.Options.G726DecOptions != nil { options.G726DecOptions = &AudioDecoderOptions{ BitrateList: resp.Options.G726DecOptions.BitrateList, } } return options, nil } // GetGuaranteedNumberOfVideoEncoderInstances retrieves the guaranteed number of video encoder instances. func (c *Client) GetGuaranteedNumberOfVideoEncoderInstances( ctx context.Context, configurationToken string, ) (*GuaranteedNumberOfVideoEncoderInstances, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetGuaranteedNumberOfVideoEncoderInstances struct { XMLName xml.Name `xml:"trt:GetGuaranteedNumberOfVideoEncoderInstances"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetGuaranteedNumberOfVideoEncoderInstancesResponse struct { XMLName xml.Name `xml:"GetGuaranteedNumberOfVideoEncoderInstancesResponse"` TotalNumber int `xml:"TotalNumber"` JPEG int `xml:"JPEG"` H264 int `xml:"H264"` MPEG4 int `xml:"MPEG4"` } req := GetGuaranteedNumberOfVideoEncoderInstances{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetGuaranteedNumberOfVideoEncoderInstancesResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetGuaranteedNumberOfVideoEncoderInstances failed: %w", err) } return &GuaranteedNumberOfVideoEncoderInstances{ TotalNumber: resp.TotalNumber, JPEG: resp.JPEG, H264: resp.H264, MPEG4: resp.MPEG4, }, nil } // GetOSDOptions retrieves available options for OSD configuration. func (c *Client) GetOSDOptions(ctx context.Context, configurationToken string) (*OSDConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetOSDOptions struct { XMLName xml.Name `xml:"trt:GetOSDOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` } type GetOSDOptionsResponse struct { XMLName xml.Name `xml:"GetOSDOptionsResponse"` Options struct { MaximumNumberOfOSDs int `xml:"MaximumNumberOfOSDs"` } `xml:"Options"` } req := GetOSDOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } var resp GetOSDOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetOSDOptions failed: %w", err) } return &OSDConfigurationOptions{ MaximumNumberOfOSDs: resp.Options.MaximumNumberOfOSDs, }, nil } // GetVideoSourceConfigurations retrieves all video source configurations. func (c *Client) GetVideoSourceConfigurations(ctx context.Context) ([]*VideoSourceConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoSourceConfigurations struct { XMLName xml.Name `xml:"trt:GetVideoSourceConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetVideoSourceConfigurationsResponse struct { XMLName xml.Name `xml:"GetVideoSourceConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` Bounds *struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` } `xml:"Bounds"` } `xml:"Configurations"` } req := GetVideoSourceConfigurations{ Xmlns: mediaNamespace, } var resp GetVideoSourceConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoSourceConfigurations failed: %w", err) } configs := make([]*VideoSourceConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { config := &VideoSourceConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, SourceToken: cfg.SourceToken, } if cfg.Bounds != nil { config.Bounds = &IntRectangle{ X: cfg.Bounds.X, Y: cfg.Bounds.Y, Width: cfg.Bounds.Width, Height: cfg.Bounds.Height, } } configs[i] = config } return configs, nil } // GetAudioSourceConfigurations retrieves all audio source configurations. func (c *Client) GetAudioSourceConfigurations(ctx context.Context) ([]*AudioSourceConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioSourceConfigurations struct { XMLName xml.Name `xml:"trt:GetAudioSourceConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioSourceConfigurationsResponse struct { XMLName xml.Name `xml:"GetAudioSourceConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` } `xml:"Configurations"` } req := GetAudioSourceConfigurations{ Xmlns: mediaNamespace, } var resp GetAudioSourceConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioSourceConfigurations failed: %w", err) } configs := make([]*AudioSourceConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioSourceConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, SourceToken: cfg.SourceToken, } } return configs, nil } // GetVideoEncoderConfigurations retrieves all video encoder configurations. func (c *Client) GetVideoEncoderConfigurations(ctx context.Context) ([]*VideoEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoEncoderConfigurations struct { XMLName xml.Name `xml:"trt:GetVideoEncoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetVideoEncoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetVideoEncoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Resolution *struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` Quality float64 `xml:"Quality"` RateControl *struct { FrameRateLimit int `xml:"FrameRateLimit"` EncodingInterval int `xml:"EncodingInterval"` BitrateLimit int `xml:"BitrateLimit"` } `xml:"RateControl"` MPEG4 *struct { GovLength int `xml:"GovLength"` MPEG4Profile string `xml:"MPEG4Profile"` } `xml:"MPEG4"` H264 *struct { GovLength int `xml:"GovLength"` H264Profile string `xml:"H264Profile"` } `xml:"H264"` Multicast *struct { Address *struct { Type string `xml:"Type"` IPv4Address string `xml:"IPv4Address"` IPv6Address string `xml:"IPv6Address"` } `xml:"Address"` Port int `xml:"Port"` TTL int `xml:"TTL"` AutoStart bool `xml:"AutoStart"` } `xml:"Multicast"` SessionTimeout string `xml:"SessionTimeout"` } `xml:"Configurations"` } req := GetVideoEncoderConfigurations{ Xmlns: mediaNamespace, } var resp GetVideoEncoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoEncoderConfigurations failed: %w", err) } configs := make([]*VideoEncoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { config := &VideoEncoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Encoding: cfg.Encoding, Quality: cfg.Quality, } if cfg.Resolution != nil { config.Resolution = &VideoResolution{ Width: cfg.Resolution.Width, Height: cfg.Resolution.Height, } } if cfg.RateControl != nil { config.RateControl = &VideoRateControl{ FrameRateLimit: cfg.RateControl.FrameRateLimit, EncodingInterval: cfg.RateControl.EncodingInterval, BitrateLimit: cfg.RateControl.BitrateLimit, } } if cfg.MPEG4 != nil { config.MPEG4 = &MPEG4Configuration{ GovLength: cfg.MPEG4.GovLength, MPEG4Profile: cfg.MPEG4.MPEG4Profile, } } if cfg.H264 != nil { config.H264 = &H264Configuration{ GovLength: cfg.H264.GovLength, H264Profile: cfg.H264.H264Profile, } } if cfg.Multicast != nil { config.Multicast = &MulticastConfiguration{ Port: cfg.Multicast.Port, TTL: cfg.Multicast.TTL, AutoStart: cfg.Multicast.AutoStart, } if cfg.Multicast.Address != nil { config.Multicast.Address = &IPAddress{ Type: cfg.Multicast.Address.Type, IPv4Address: cfg.Multicast.Address.IPv4Address, IPv6Address: cfg.Multicast.Address.IPv6Address, } } } configs[i] = config } return configs, nil } // GetAudioEncoderConfigurations retrieves all audio encoder configurations. func (c *Client) GetAudioEncoderConfigurations(ctx context.Context) ([]*AudioEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioEncoderConfigurations struct { XMLName xml.Name `xml:"trt:GetAudioEncoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioEncoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetAudioEncoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Bitrate int `xml:"Bitrate"` SampleRate int `xml:"SampleRate"` Multicast *struct { Address *struct { Type string `xml:"Type"` IPv4Address string `xml:"IPv4Address"` IPv6Address string `xml:"IPv6Address"` } `xml:"Address"` Port int `xml:"Port"` TTL int `xml:"TTL"` AutoStart bool `xml:"AutoStart"` } `xml:"Multicast"` SessionTimeout string `xml:"SessionTimeout"` } `xml:"Configurations"` } req := GetAudioEncoderConfigurations{ Xmlns: mediaNamespace, } var resp GetAudioEncoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioEncoderConfigurations failed: %w", err) } configs := make([]*AudioEncoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { config := &AudioEncoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Encoding: cfg.Encoding, Bitrate: cfg.Bitrate, SampleRate: cfg.SampleRate, } if cfg.Multicast != nil { config.Multicast = &MulticastConfiguration{ Port: cfg.Multicast.Port, TTL: cfg.Multicast.TTL, AutoStart: cfg.Multicast.AutoStart, } if cfg.Multicast.Address != nil { config.Multicast.Address = &IPAddress{ Type: cfg.Multicast.Address.Type, IPv4Address: cfg.Multicast.Address.IPv4Address, IPv6Address: cfg.Multicast.Address.IPv6Address, } } } configs[i] = config } return configs, nil } // GetVideoSourceConfiguration retrieves a specific video source configuration. func (c *Client) GetVideoSourceConfiguration( ctx context.Context, configurationToken string, ) (*VideoSourceConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoSourceConfiguration struct { XMLName xml.Name `xml:"trt:GetVideoSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetVideoSourceConfigurationResponse struct { XMLName xml.Name `xml:"GetVideoSourceConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` Bounds *struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` } `xml:"Bounds"` } `xml:"Configuration"` } req := GetVideoSourceConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetVideoSourceConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoSourceConfiguration failed: %w", err) } config := &VideoSourceConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, SourceToken: resp.Configuration.SourceToken, } if resp.Configuration.Bounds != nil { config.Bounds = &IntRectangle{ X: resp.Configuration.Bounds.X, Y: resp.Configuration.Bounds.Y, Width: resp.Configuration.Bounds.Width, Height: resp.Configuration.Bounds.Height, } } return config, nil } // GetAudioSourceConfiguration retrieves a specific audio source configuration. func (c *Client) GetAudioSourceConfiguration(ctx context.Context, configurationToken string) (*AudioSourceConfiguration, error) { endpoint := c.getMediaEndpoint() type GetAudioSourceConfiguration struct { XMLName xml.Name `xml:"trt:GetAudioSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetAudioSourceConfigurationResponse struct { XMLName xml.Name `xml:"GetAudioSourceConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` } `xml:"Configuration"` } req := GetAudioSourceConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetAudioSourceConfigurationResponse soapClient := c.getMediaSoapClient() if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioSourceConfiguration failed: %w", err) } return &AudioSourceConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, SourceToken: resp.Configuration.SourceToken, }, nil } // GetVideoSourceConfigurationOptions retrieves available options for video source configuration. func (c *Client) GetVideoSourceConfigurationOptions( ctx context.Context, configurationToken, profileToken string, ) (*VideoSourceConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoSourceConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetVideoSourceConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetVideoSourceConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetVideoSourceConfigurationOptionsResponse"` Options struct { BoundsRange *struct { X *IntRange `xml:"X"` Y *IntRange `xml:"Y"` Width *IntRange `xml:"Width"` Height *IntRange `xml:"Height"` } `xml:"BoundsRange"` VideoSourceTokensAvailable []string `xml:"VideoSourceTokensAvailable"` } `xml:"Options"` } req := GetVideoSourceConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } if profileToken != "" { req.ProfileToken = profileToken } var resp GetVideoSourceConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoSourceConfigurationOptions failed: %w", err) } options := &VideoSourceConfigurationOptions{} if resp.Options.BoundsRange != nil { options.BoundsRange = &BoundsRange{ X: resp.Options.BoundsRange.X, Y: resp.Options.BoundsRange.Y, Width: resp.Options.BoundsRange.Width, Height: resp.Options.BoundsRange.Height, } } options.VideoSourceTokensAvailable = resp.Options.VideoSourceTokensAvailable return options, nil } // GetAudioSourceConfigurationOptions retrieves available options for audio source configuration. func (c *Client) GetAudioSourceConfigurationOptions( ctx context.Context, configurationToken, profileToken string, ) (*AudioSourceConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioSourceConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetAudioSourceConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetAudioSourceConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetAudioSourceConfigurationOptionsResponse"` Options struct { InputTokensAvailable []string `xml:"InputTokensAvailable"` } `xml:"Options"` } req := GetAudioSourceConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } if profileToken != "" { req.ProfileToken = profileToken } var resp GetAudioSourceConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioSourceConfigurationOptions failed: %w", err) } return &AudioSourceConfigurationOptions{ InputTokensAvailable: resp.Options.InputTokensAvailable, }, nil } // SetVideoSourceConfiguration sets video source configuration. func (c *Client) SetVideoSourceConfiguration( ctx context.Context, config *VideoSourceConfiguration, forcePersistence bool, ) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetVideoSourceConfiguration struct { XMLName xml.Name `xml:"trt:SetVideoSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` SourceToken string `xml:"tt:SourceToken"` Bounds *struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` } `xml:"tt:Bounds,omitempty"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetVideoSourceConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.SourceToken = config.SourceToken if config.Bounds != nil { req.Configuration.Bounds = &struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` }{ X: config.Bounds.X, Y: config.Bounds.Y, Width: config.Bounds.Width, Height: config.Bounds.Height, } } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetVideoSourceConfiguration failed: %w", err) } return nil } // SetAudioSourceConfiguration sets audio source configuration. func (c *Client) SetAudioSourceConfiguration(ctx context.Context, config *AudioSourceConfiguration, forcePersistence bool) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetAudioSourceConfiguration struct { XMLName xml.Name `xml:"trt:SetAudioSourceConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` SourceToken string `xml:"tt:SourceToken"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetAudioSourceConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount req.Configuration.SourceToken = config.SourceToken username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetAudioSourceConfiguration failed: %w", err) } return nil } // GetCompatibleVideoEncoderConfigurations retrieves compatible video encoder configurations for a profile. func (c *Client) GetCompatibleVideoEncoderConfigurations( ctx context.Context, profileToken string, ) ([]*VideoEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleVideoEncoderConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleVideoEncoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleVideoEncoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleVideoEncoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Resolution *struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` Quality float64 `xml:"Quality"` RateControl *struct { FrameRateLimit int `xml:"FrameRateLimit"` EncodingInterval int `xml:"EncodingInterval"` BitrateLimit int `xml:"BitrateLimit"` } `xml:"RateControl"` } `xml:"Configurations"` } req := GetCompatibleVideoEncoderConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleVideoEncoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleVideoEncoderConfigurations failed: %w", err) } configs := make([]*VideoEncoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { config := &VideoEncoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Encoding: cfg.Encoding, Quality: cfg.Quality, } if cfg.Resolution != nil { config.Resolution = &VideoResolution{ Width: cfg.Resolution.Width, Height: cfg.Resolution.Height, } } if cfg.RateControl != nil { config.RateControl = &VideoRateControl{ FrameRateLimit: cfg.RateControl.FrameRateLimit, EncodingInterval: cfg.RateControl.EncodingInterval, BitrateLimit: cfg.RateControl.BitrateLimit, } } configs[i] = config } return configs, nil } // GetCompatibleVideoSourceConfigurations retrieves compatible video source configurations for a profile. func (c *Client) GetCompatibleVideoSourceConfigurations( ctx context.Context, profileToken string, ) ([]*VideoSourceConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleVideoSourceConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleVideoSourceConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleVideoSourceConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleVideoSourceConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` Bounds *struct { X int `xml:"x,attr"` Y int `xml:"y,attr"` Width int `xml:"width,attr"` Height int `xml:"height,attr"` } `xml:"Bounds"` } `xml:"Configurations"` } req := GetCompatibleVideoSourceConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleVideoSourceConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleVideoSourceConfigurations failed: %w", err) } configs := make([]*VideoSourceConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { config := &VideoSourceConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, SourceToken: cfg.SourceToken, } if cfg.Bounds != nil { config.Bounds = &IntRectangle{ X: cfg.Bounds.X, Y: cfg.Bounds.Y, Width: cfg.Bounds.Width, Height: cfg.Bounds.Height, } } configs[i] = config } return configs, nil } // GetCompatibleAudioEncoderConfigurations retrieves compatible audio encoder configurations for a profile. func (c *Client) GetCompatibleAudioEncoderConfigurations( ctx context.Context, profileToken string, ) ([]*AudioEncoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleAudioEncoderConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleAudioEncoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleAudioEncoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleAudioEncoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Encoding string `xml:"Encoding"` Bitrate int `xml:"Bitrate"` SampleRate int `xml:"SampleRate"` } `xml:"Configurations"` } req := GetCompatibleAudioEncoderConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleAudioEncoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleAudioEncoderConfigurations failed: %w", err) } configs := make([]*AudioEncoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioEncoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Encoding: cfg.Encoding, Bitrate: cfg.Bitrate, SampleRate: cfg.SampleRate, } } return configs, nil } // GetCompatibleAudioSourceConfigurations retrieves compatible audio source configurations for a profile. func (c *Client) GetCompatibleAudioSourceConfigurations(ctx context.Context, profileToken string) ([]*AudioSourceConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleAudioSourceConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleAudioSourceConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleAudioSourceConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleAudioSourceConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` SourceToken string `xml:"SourceToken"` } `xml:"Configurations"` } req := GetCompatibleAudioSourceConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleAudioSourceConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleAudioSourceConfigurations failed: %w", err) } configs := make([]*AudioSourceConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioSourceConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, SourceToken: cfg.SourceToken, } } return configs, nil } // GetCompatiblePTZConfigurations retrieves compatible PTZ configurations for a profile. func (c *Client) GetCompatiblePTZConfigurations(ctx context.Context, profileToken string) ([]*PTZConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatiblePTZConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatiblePTZConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatiblePTZConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatiblePTZConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` NodeToken string `xml:"NodeToken"` } `xml:"Configurations"` } req := GetCompatiblePTZConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatiblePTZConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatiblePTZConfigurations failed: %w", err) } configs := make([]*PTZConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &PTZConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, NodeToken: cfg.NodeToken, } } return configs, nil } // GetCompatibleMetadataConfigurations retrieves compatible metadata configurations for a profile. func (c *Client) GetCompatibleMetadataConfigurations(ctx context.Context, profileToken string) ([]*MetadataConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleMetadataConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleMetadataConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleMetadataConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleMetadataConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Analytics bool `xml:"Analytics"` } `xml:"Configurations"` } req := GetCompatibleMetadataConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleMetadataConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleMetadataConfigurations failed: %w", err) } configs := make([]*MetadataConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &MetadataConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Analytics: cfg.Analytics, } } return configs, nil } // GetCompatibleAudioOutputConfigurations retrieves compatible audio output configurations for a profile. func (c *Client) GetCompatibleAudioOutputConfigurations(ctx context.Context, profileToken string) ([]*AudioOutputConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleAudioOutputConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleAudioOutputConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleAudioOutputConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleAudioOutputConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` OutputToken string `xml:"OutputToken"` } `xml:"Configurations"` } req := GetCompatibleAudioOutputConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleAudioOutputConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleAudioOutputConfigurations failed: %w", err) } configs := make([]*AudioOutputConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioOutputConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, OutputToken: cfg.OutputToken, } } return configs, nil } // GetCompatibleAudioDecoderConfigurations retrieves compatible audio decoder configurations for a profile. func (c *Client) GetCompatibleAudioDecoderConfigurations(ctx context.Context, profileToken string) ([]*AudioDecoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleAudioDecoderConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleAudioDecoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleAudioDecoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleAudioDecoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configurations"` } req := GetCompatibleAudioDecoderConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleAudioDecoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleAudioDecoderConfigurations failed: %w", err) } configs := make([]*AudioDecoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioDecoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, } } return configs, nil } // GetMetadataConfigurations retrieves all metadata configurations. func (c *Client) GetMetadataConfigurations(ctx context.Context) ([]*MetadataConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetMetadataConfigurations struct { XMLName xml.Name `xml:"trt:GetMetadataConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetMetadataConfigurationsResponse struct { XMLName xml.Name `xml:"GetMetadataConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` Analytics bool `xml:"Analytics"` } `xml:"Configurations"` } req := GetMetadataConfigurations{ Xmlns: mediaNamespace, } var resp GetMetadataConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetMetadataConfigurations failed: %w", err) } configs := make([]*MetadataConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &MetadataConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, Analytics: cfg.Analytics, } } return configs, nil } // GetAudioOutputConfigurations retrieves all audio output configurations. func (c *Client) GetAudioOutputConfigurations(ctx context.Context) ([]*AudioOutputConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioOutputConfigurations struct { XMLName xml.Name `xml:"trt:GetAudioOutputConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioOutputConfigurationsResponse struct { XMLName xml.Name `xml:"GetAudioOutputConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` OutputToken string `xml:"OutputToken"` } `xml:"Configurations"` } req := GetAudioOutputConfigurations{ Xmlns: mediaNamespace, } var resp GetAudioOutputConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioOutputConfigurations failed: %w", err) } configs := make([]*AudioOutputConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioOutputConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, OutputToken: cfg.OutputToken, } } return configs, nil } // GetAudioDecoderConfigurations retrieves all audio decoder configurations. func (c *Client) GetAudioDecoderConfigurations(ctx context.Context) ([]*AudioDecoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioDecoderConfigurations struct { XMLName xml.Name `xml:"trt:GetAudioDecoderConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetAudioDecoderConfigurationsResponse struct { XMLName xml.Name `xml:"GetAudioDecoderConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configurations"` } req := GetAudioDecoderConfigurations{ Xmlns: mediaNamespace, } var resp GetAudioDecoderConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioDecoderConfigurations failed: %w", err) } configs := make([]*AudioDecoderConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &AudioDecoderConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, } } return configs, nil } // GetAudioDecoderConfiguration retrieves a specific audio decoder configuration. func (c *Client) GetAudioDecoderConfiguration( ctx context.Context, configurationToken string, ) (*AudioDecoderConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetAudioDecoderConfiguration struct { XMLName xml.Name `xml:"trt:GetAudioDecoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetAudioDecoderConfigurationResponse struct { XMLName xml.Name `xml:"GetAudioDecoderConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configuration"` } req := GetAudioDecoderConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetAudioDecoderConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetAudioDecoderConfiguration failed: %w", err) } return &AudioDecoderConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, }, nil } // SetAudioDecoderConfiguration sets audio decoder configuration. func (c *Client) SetAudioDecoderConfiguration(ctx context.Context, config *AudioDecoderConfiguration, forcePersistence bool) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetAudioDecoderConfiguration struct { XMLName xml.Name `xml:"trt:SetAudioDecoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetAudioDecoderConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetAudioDecoderConfiguration failed: %w", err) } return nil } // GetVideoAnalyticsConfigurations retrieves all video analytics configurations. func (c *Client) GetVideoAnalyticsConfigurations(ctx context.Context) ([]*VideoAnalyticsConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoAnalyticsConfigurations struct { XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` } type GetVideoAnalyticsConfigurationsResponse struct { XMLName xml.Name `xml:"GetVideoAnalyticsConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configurations"` } req := GetVideoAnalyticsConfigurations{ Xmlns: mediaNamespace, } var resp GetVideoAnalyticsConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoAnalyticsConfigurations failed: %w", err) } configs := make([]*VideoAnalyticsConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &VideoAnalyticsConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, } } return configs, nil } // GetVideoAnalyticsConfiguration retrieves a specific video analytics configuration. func (c *Client) GetVideoAnalyticsConfiguration( ctx context.Context, configurationToken string, ) (*VideoAnalyticsConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoAnalyticsConfiguration struct { XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } type GetVideoAnalyticsConfigurationResponse struct { XMLName xml.Name `xml:"GetVideoAnalyticsConfigurationResponse"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configuration"` } req := GetVideoAnalyticsConfiguration{ Xmlns: mediaNamespace, ConfigurationToken: configurationToken, } var resp GetVideoAnalyticsConfigurationResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoAnalyticsConfiguration failed: %w", err) } return &VideoAnalyticsConfiguration{ Token: resp.Configuration.Token, Name: resp.Configuration.Name, UseCount: resp.Configuration.UseCount, }, nil } // GetCompatibleVideoAnalyticsConfigurations retrieves compatible video analytics configurations for a profile. func (c *Client) GetCompatibleVideoAnalyticsConfigurations(ctx context.Context, profileToken string) ([]*VideoAnalyticsConfiguration, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetCompatibleVideoAnalyticsConfigurations struct { XMLName xml.Name `xml:"trt:GetCompatibleVideoAnalyticsConfigurations"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } type GetCompatibleVideoAnalyticsConfigurationsResponse struct { XMLName xml.Name `xml:"GetCompatibleVideoAnalyticsConfigurationsResponse"` Configurations []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` UseCount int `xml:"UseCount"` } `xml:"Configurations"` } req := GetCompatibleVideoAnalyticsConfigurations{ Xmlns: mediaNamespace, ProfileToken: profileToken, } var resp GetCompatibleVideoAnalyticsConfigurationsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetCompatibleVideoAnalyticsConfigurations failed: %w", err) } configs := make([]*VideoAnalyticsConfiguration, len(resp.Configurations)) for i, cfg := range resp.Configurations { configs[i] = &VideoAnalyticsConfiguration{ Token: cfg.Token, Name: cfg.Name, UseCount: cfg.UseCount, } } return configs, nil } // SetVideoAnalyticsConfiguration sets video analytics configuration. func (c *Client) SetVideoAnalyticsConfiguration(ctx context.Context, config *VideoAnalyticsConfiguration, forcePersistence bool) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type SetVideoAnalyticsConfiguration struct { XMLName xml.Name `xml:"trt:SetVideoAnalyticsConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` Xmlnst string `xml:"xmlns:tt,attr"` Configuration struct { Token string `xml:"token,attr"` Name string `xml:"tt:Name"` UseCount int `xml:"tt:UseCount"` } `xml:"trt:Configuration"` ForcePersistence bool `xml:"trt:ForcePersistence"` } req := SetVideoAnalyticsConfiguration{ Xmlns: mediaNamespace, Xmlnst: "http://www.onvif.org/ver10/schema", ForcePersistence: forcePersistence, } req.Configuration.Token = config.Token req.Configuration.Name = config.Name req.Configuration.UseCount = config.UseCount username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("SetVideoAnalyticsConfiguration failed: %w", err) } return nil } // GetVideoAnalyticsConfigurationOptions retrieves available options for video analytics configuration. func (c *Client) GetVideoAnalyticsConfigurationOptions( ctx context.Context, configurationToken, profileToken string, ) (*VideoAnalyticsConfigurationOptions, error) { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type GetVideoAnalyticsConfigurationOptions struct { XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfigurationOptions"` Xmlns string `xml:"xmlns:trt,attr"` ConfigurationToken string `xml:"trt:ConfigurationToken,omitempty"` ProfileToken string `xml:"trt:ProfileToken,omitempty"` } type GetVideoAnalyticsConfigurationOptionsResponse struct { XMLName xml.Name `xml:"GetVideoAnalyticsConfigurationOptionsResponse"` Options struct{} `xml:"Options"` } req := GetVideoAnalyticsConfigurationOptions{ Xmlns: mediaNamespace, } if configurationToken != "" { req.ConfigurationToken = configurationToken } if profileToken != "" { req.ProfileToken = profileToken } var resp GetVideoAnalyticsConfigurationOptionsResponse username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil { return nil, fmt.Errorf("GetVideoAnalyticsConfigurationOptions failed: %w", err) } return &VideoAnalyticsConfigurationOptions{}, nil } // AddVideoAnalyticsConfiguration adds a video analytics configuration to a profile. func (c *Client) AddVideoAnalyticsConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddVideoAnalyticsConfiguration struct { XMLName xml.Name `xml:"trt:AddVideoAnalyticsConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddVideoAnalyticsConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddVideoAnalyticsConfiguration failed: %w", err) } return nil } // RemoveVideoAnalyticsConfiguration removes a video analytics configuration from a profile. func (c *Client) RemoveVideoAnalyticsConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveVideoAnalyticsConfiguration struct { XMLName xml.Name `xml:"trt:RemoveVideoAnalyticsConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveVideoAnalyticsConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveVideoAnalyticsConfiguration failed: %w", err) } return nil } // AddAudioOutputConfiguration adds an audio output configuration to a profile. func (c *Client) AddAudioOutputConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddAudioOutputConfiguration struct { XMLName xml.Name `xml:"trt:AddAudioOutputConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddAudioOutputConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddAudioOutputConfiguration failed: %w", err) } return nil } // RemoveAudioOutputConfiguration removes an audio output configuration from a profile. func (c *Client) RemoveAudioOutputConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveAudioOutputConfiguration struct { XMLName xml.Name `xml:"trt:RemoveAudioOutputConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveAudioOutputConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveAudioOutputConfiguration failed: %w", err) } return nil } // AddAudioDecoderConfiguration adds an audio decoder configuration to a profile. func (c *Client) AddAudioDecoderConfiguration(ctx context.Context, profileToken, configurationToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type AddAudioDecoderConfiguration struct { XMLName xml.Name `xml:"trt:AddAudioDecoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` ConfigurationToken string `xml:"trt:ConfigurationToken"` } req := AddAudioDecoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, ConfigurationToken: configurationToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("AddAudioDecoderConfiguration failed: %w", err) } return nil } // RemoveAudioDecoderConfiguration removes an audio decoder configuration from a profile. func (c *Client) RemoveAudioDecoderConfiguration(ctx context.Context, profileToken string) error { endpoint := c.mediaEndpoint if endpoint == "" { endpoint = c.endpoint } type RemoveAudioDecoderConfiguration struct { XMLName xml.Name `xml:"trt:RemoveAudioDecoderConfiguration"` Xmlns string `xml:"xmlns:trt,attr"` ProfileToken string `xml:"trt:ProfileToken"` } req := RemoveAudioDecoderConfiguration{ Xmlns: mediaNamespace, ProfileToken: profileToken, } username, password := c.GetCredentials() soapClient := soap.NewClient(c.httpClient, username, password) if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil { return fmt.Errorf("RemoveAudioDecoderConfiguration failed: %w", err) } return nil }