github.com/qiniu/go-sdk/v7@v7.27.0/qvs/stream.go (about)

     1  package qvs
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  )
     9  
    10  const (
    11  	DomainPublishRTMP string = "publishRtmp"
    12  	DomainLiveRTMP    string = "liveRtmp"
    13  	DomainLiveHLS     string = "liveHls"
    14  	DomainLiveHDL     string = "liveHdl"
    15  )
    16  
    17  type Stream struct {
    18  	StreamID string `json:"streamId"`       // 流名称, 流名称在空间中唯一,可包含 字母、数字、中划线、下划线;1 ~ 100 个字符长;创建后将不可修改
    19  	Desc     string `json:"desc,omitempty"` // 关于流的描述信息
    20  
    21  	NamespaceId string `json:"nsId"`   // 所属的空间ID
    22  	Namespace   string `json:"nsName"` // 所属的空间名称
    23  
    24  	RecordTemplateId   string `json:"recordTemplateId"`   // 录制模版ID,配置流维度的录制模板
    25  	SnapShotTemplateId string `json:"snapshotTemplateId"` // 截图模版ID,配置流维度的截图模板
    26  
    27  	Status       bool  `json:"status"`       // 设备是否在线
    28  	Disabled     bool  `json:"disabled"`     // 流是否被禁用
    29  	LastPushedAt int64 `json:"lastPushedAt"` // 最后一次推流时间,0:表示没有推流
    30  
    31  	CreatedAt int64 `json:"createdAt,omitempty"` // 流创建时间
    32  	UpdatedAt int64 `json:"updatedAt,omitempty"` // 流更新时间
    33  
    34  	// 以下字段只有在设备在线是才会出现
    35  	UserCount      int    `json:"userCount"`
    36  	ClientIp       string `json:"clientIp,omitempty"`
    37  	AudioFrameRate int64  `json:"audioFrameRate,omitempty"`
    38  	BitRate        int64  `json:"bitRate,omitempty"`
    39  	VideoFrameRate int64  `json:"videoFrameRate,omitempty"`
    40  }
    41  
    42  /*
    43  创建流API
    44  */
    45  func (manager *Manager) AddStream(nsId string, stream *Stream) (*Stream, error) {
    46  	var ret Stream
    47  	err := manager.client.CallWithJson(context.Background(), &ret, "POST", manager.url("/namespaces/%s/streams", nsId), nil, stream)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return &ret, nil
    52  }
    53  
    54  /*
    55  查询流API
    56  */
    57  func (manager *Manager) QueryStream(nsId string, streamId string) (*Stream, error) {
    58  	var ret Stream
    59  	err := manager.client.Call(context.Background(), &ret, "GET", manager.url("/namespaces/%s/streams/%s", nsId, streamId), nil)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return &ret, nil
    64  }
    65  
    66  /*
    67  更新流API
    68  */
    69  func (manager *Manager) UpdateStream(nsId string, streamId string, ops []PatchOperation) (*Stream, error) {
    70  	req := M{"operations": ops}
    71  	var ret Stream
    72  	err := manager.client.CallWithJson(context.Background(), &ret, "PATCH", manager.url("/namespaces/%s/streams/%s", nsId, streamId), nil, req)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return &ret, nil
    77  }
    78  
    79  /*
    80  删除流API
    81  */
    82  func (manager *Manager) DeleteStream(nsId string, streamId string) error {
    83  	return manager.client.Call(context.Background(), nil, "DELETE", manager.url("/namespaces/%s/streams/%s", nsId, streamId), nil)
    84  }
    85  
    86  /*
    87  查询流列表API
    88  */
    89  func (manager *Manager) ListStream(nsId string, offset, line int, prefix, sortBy string, qType int) ([]Stream, int64, error) {
    90  	ret := struct {
    91  		Items []Stream `json:"items"`
    92  		Total int64    `json:"total"`
    93  	}{}
    94  
    95  	query := url.Values{}
    96  	setQuery(query, "offset", offset)
    97  	setQuery(query, "line", line)
    98  	setQuery(query, "sortBy", sortBy)
    99  	setQuery(query, "prefix", prefix)
   100  	setQuery(query, "qtype", qType)
   101  
   102  	err := manager.client.Call(context.Background(), &ret, "GET", manager.url("/namespaces/%s/streams?%v", nsId, query.Encode()), nil)
   103  	return ret.Items, ret.Total, err
   104  }
   105  
   106  type DynamicLiveRoute struct {
   107  	PublishIP     string `json:"publishIP"`     // 推流端对外IP地址
   108  	PlayIP        string `json:"playIP"`        // 拉流端对外IP地址
   109  	UrlExpireSec  int64  `json:"urlExpireSec"`  // 地址过期时间,urlExpireSec:100代表100秒后过期;  默认urlExpireSec:0,永不过期.
   110  	PlayExpireSec int64  `json:"playExpireSec"` // 播放过期时间(单位为秒)
   111  }
   112  
   113  type StaticLiveRoute struct {
   114  	Domain        string `json:"domain"`        // 域名
   115  	DomainType    string `json:"domainType"`    // 域名类型
   116  	UrlExpireSec  int64  `json:"urlExpireSec"`  // 地址过期时间,urlExpireSec:100代表100秒后过期;  默认urlExpireSec:0,永不过期.
   117  	PlayExpireSec int64  `json:"playExpireSec"` // 播放过期时间(单位为秒)
   118  }
   119  
   120  type RouteRet struct {
   121  	PublishUrl        string        `json:"publishUrl"`        // rtmp推流地址
   122  	PlayUrls          RoutePlayUrls `json:"playUrls"`          // 拉流URLs
   123  	PublishUrlExpired int64         `json:"publishUrlExpired"` // 推拉流地址过期时间点(unix时间戳,单位second)
   124  }
   125  
   126  type RoutePlayUrls struct {
   127  	Rtmp string `json:"rtmp"` // rtmp播放地址
   128  	Flv  string `json:"flv"`  // flv播放地址
   129  	Hls  string `json:"hls"`  // hls播放地址
   130  }
   131  
   132  /*
   133  动态获取流地址API:推拉流IP地址计算最合适的设备端推拉流地址
   134  */
   135  func (manager *Manager) DynamicPublishPlayURL(nsId string, streamId string, route *DynamicLiveRoute) (*RouteRet, error) {
   136  	var ret RouteRet
   137  	err := manager.client.CallWithJson(context.Background(), &ret, "POST", manager.url("/namespaces/%s/streams/%s/urls", nsId, streamId), nil, route)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	return &ret, nil
   142  }
   143  
   144  /*
   145  静态获取流地址API:根据domain生成推拉流地址
   146  */
   147  func (manager *Manager) StaticPublishPlayURL(nsId, streamId string, route *StaticLiveRoute) (string, error) {
   148  	var ret RouteRet
   149  	err := manager.client.CallWithJson(context.Background(), &ret, "POST", manager.url("/namespaces/%s/streams/%s/domain", nsId, streamId), nil, route)
   150  	if err != nil {
   151  		return "", err
   152  	}
   153  	switch route.DomainType {
   154  	case DomainPublishRTMP:
   155  		return ret.PublishUrl, nil
   156  	case DomainLiveRTMP:
   157  		return ret.PlayUrls.Rtmp, nil
   158  	case DomainLiveHLS:
   159  		return ret.PlayUrls.Hls, nil
   160  	case DomainLiveHDL:
   161  		return ret.PlayUrls.Flv, nil
   162  	}
   163  	return "", nil
   164  }
   165  
   166  // 禁用流
   167  func (manager *Manager) DisableStream(nsId string, streamId string) error {
   168  	err := manager.client.CallWithJson(context.Background(), nil, "POST", manager.url("/namespaces/%s/streams/%s/disabled", nsId, streamId), nil, nil)
   169  	return err
   170  }
   171  
   172  // 恢复流
   173  func (manager *Manager) EnableStream(nsId string, streamId string) error {
   174  	err := manager.client.CallWithJson(context.Background(), nil, "POST", manager.url("/namespaces/%s/streams/%s/enabled", nsId, streamId), nil, nil)
   175  	return err
   176  }
   177  
   178  // 停止推流
   179  func (manager *Manager) StopStream(nsId string, streamId string) error {
   180  	err := manager.client.CallWithJson(context.Background(), nil, "POST", manager.url("/namespaces/%s/streams/%s/stop", nsId, streamId), nil, nil)
   181  	return err
   182  }
   183  
   184  type StreamPublishHistory struct {
   185  	StreamId string `json:"streamId"`
   186  	NsId     string `json:"nsId"`
   187  	Start    int64  `json:"start"`
   188  	End      int64  `json:"end"`
   189  	Duration int64  `json:"duration"`
   190  	Snap     string `json:"snap"`
   191  	Fmt      string `json:"format,omitempty"`
   192  }
   193  
   194  // 查询推流历史记录
   195  func (manager *Manager) QueryStreamPubhistories(nsId string, streamId string, start, end int, line, offset int) ([]StreamPublishHistory, int64, error) {
   196  	ret := struct {
   197  		Items []StreamPublishHistory `json:"items"`
   198  		Total int64                  `json:"total"`
   199  	}{}
   200  
   201  	query := url.Values{}
   202  	setQuery(query, "start", start)
   203  	setQuery(query, "end", end)
   204  	setQuery(query, "offset", offset)
   205  	setQuery(query, "line", line)
   206  
   207  	err := manager.client.Call(context.Background(), &ret, "GET", manager.url("/namespaces/%s/streams/%s/pubhistories?%v", nsId, streamId, query.Encode()), nil)
   208  	return ret.Items, ret.Total, err
   209  }
   210  
   211  // 按需截图
   212  func (manager *Manager) OndemandSnap(nsId, streamId string) error {
   213  	return manager.client.CallWithJson(context.Background(), nil, "POST", manager.url("/namespaces/%s/streams/%s/snap", nsId, streamId), nil, nil)
   214  }
   215  
   216  // 删除截图
   217  func (manager *Manager) DeleteSnapshots(nsId, streamId string, files []string) error {
   218  	return manager.client.CallWithJson(context.Background(), nil, "DELETE", manager.url("/namespaces/%s/streams/%s/snapshots", nsId, streamId), nil, M{"files": files})
   219  }
   220  
   221  // 查询截图列表
   222  func (manager *Manager) StreamsSnapshots(nsId string, streamId string, start, end int, qtype int, line int, marker string) ([]byte, error) {
   223  	query := url.Values{}
   224  	setQuery(query, "start", start)
   225  	setQuery(query, "end", end)
   226  	setQuery(query, "type", qtype)
   227  	setQuery(query, "line", line)
   228  	setQuery(query, "marker", marker)
   229  
   230  	req, err := http.NewRequest("GET", manager.url("/namespaces/%s/streams/%s/snapshots?%v", nsId, streamId, query.Encode()), nil)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  	resp, err := manager.client.Do(context.Background(), req)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	body, err := io.ReadAll(resp.Body)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	return body, nil
   243  }
   244  
   245  type RecordHistory struct {
   246  	Url      string `json:"url"`
   247  	Start    int    `json:"start"`
   248  	End      int    `json:"end"`
   249  	Duration int    `json:"duration"`
   250  	Format   int    `json:"format"`
   251  	Snap     string `json:"snap"`
   252  	File     string `json:"file"`
   253  }
   254  
   255  // 查询视频流的录制记录
   256  func (manager *Manager) QueryStreamRecordHistories(nsId string, streamId string, start, end int, marker string, line int, format string) ([]RecordHistory, string, error) {
   257  	ret := struct {
   258  		Items  []RecordHistory `json:"items"`
   259  		Marker string          `json:"marker"`
   260  	}{}
   261  
   262  	query := url.Values{}
   263  	setQuery(query, "start", start)
   264  	setQuery(query, "end", end)
   265  	setQuery(query, "marker", marker)
   266  	setQuery(query, "line", line)
   267  	setQuery(query, "format", format)
   268  
   269  	err := manager.client.Call(context.Background(), &ret, "GET", manager.url("/namespaces/%s/streams/%s/recordhistories?%v", nsId, streamId, query.Encode()), nil)
   270  	return ret.Items, ret.Marker, err
   271  }
   272  
   273  // 查询流封面
   274  func (manager *Manager) QueryStreamCover(nsId string, streamId string) (string, error) {
   275  	ret := struct {
   276  		Url string `json:"url"`
   277  	}{}
   278  	err := manager.client.Call(context.Background(), &ret, "GET", manager.url("/namespaces/%s/streams/%s/cover", nsId, streamId), nil)
   279  	return ret.Url, err
   280  }