NextGB, web demo powerd by vue

This commit is contained in:
chenhaibo
2025-02-03 16:27:46 +08:00
parent 0b7126b12b
commit c80247286e
113 changed files with 16731 additions and 9944 deletions
+77
View File
@@ -0,0 +1,77 @@
package media
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"time"
"github.com/ossrs/go-oryx-lib/errors"
"github.com/ossrs/go-oryx-lib/logger"
)
type IMedia interface {
Publish(id, ssrc string) (int, error)
Unpublish(id string) error
GetStreamStatus(id string) (bool, error)
GetAddr() string
GetWebRTCAddr(id string) string
}
// The r is HTTP API to request, like "http://localhost:1985/gb/v1/publish".
// The req is the HTTP request body, will be marshal to JSON object. nil is no body
// The res is the HTTP response body, already unmarshal to JSON object.
func apiRequest(ctx context.Context, r string, req interface{}, res interface{}) error {
var buf bytes.Buffer
if req != nil {
if err := json.NewEncoder(&buf).Encode(req); err != nil {
return errors.Wrapf(err, "Marshal body %v", req)
}
}
logger.Tf(ctx, "Request url api=%v with %v bytes", r, buf.Len())
method := "POST"
if req == nil {
method = "GET"
}
reqObj, err := http.NewRequest(method, r, &buf)
if err != nil {
return errors.Wrapf(err, "HTTP request %v", buf.String())
}
client := &http.Client{Timeout: 10 * time.Second}
resObj, err := client.Do(reqObj.WithContext(ctx))
if err != nil {
return errors.Wrapf(err, "Do HTTP request %v", buf.String())
}
defer resObj.Body.Close()
if resObj.StatusCode != http.StatusOK {
return errors.Errorf("Server returned status code=%v", resObj.StatusCode)
}
b2, err := io.ReadAll(resObj.Body)
if err != nil {
return errors.Wrapf(err, "Read response for %v", buf.String())
}
logger.Tf(ctx, "Response from %v is %v bytes", r, len(b2))
errorCode := struct {
Code int `json:"code"`
}{}
if err := json.Unmarshal(b2, &errorCode); err != nil {
return errors.Wrapf(err, "Unmarshal %v", string(b2))
}
if errorCode.Code != 0 {
return errors.Errorf("Server fail code=%v %v", errorCode.Code, string(b2))
}
if err := json.Unmarshal(b2, res); err != nil {
return errors.Wrapf(err, "Unmarshal %v", string(b2))
}
logger.Tf(ctx, "Parse response to code=%v ok, %v", errorCode.Code, res)
return nil
}
+106
View File
@@ -0,0 +1,106 @@
package media
import (
"context"
"github.com/ossrs/go-oryx-lib/errors"
)
type Srs struct {
Ctx context.Context
Schema string // The schema of SRS, eg: http
Addr string // The address of SRS, eg: localhost:1985
Username string // The username of SRS, eg: admin
Password string // The password of SRS, eg: 123456
}
func (s *Srs) Publish(id, ssrc string) (int, error) {
req := struct {
Id string `json:"id"`
SSRC string `json:"ssrc"`
}{
id, ssrc,
}
res := struct {
Code int `json:"code"`
Port int `json:"port"`
}{}
if err := apiRequest(s.Ctx, s.Schema+"://"+s.Addr+"/gb/v1/publish/", req, &res); err != nil {
return 0, errors.Wrapf(err, "gb/v1/publish")
}
return res.Port, nil
}
func (s *Srs) Unpublish(id string) error {
return nil
}
// {
// "code": 0,
// "server": "vid-y19n6nm",
// "service": "382k456r",
// "pid": "9495",
// "streams": [{
// "id": "vid-9y0ozy0",
// "name": "0551954854",
// "vhost": "vid-v2ws53u",
// "app": "live",
// "tcUrl": "webrtc://127.0.0.1:1985/live",
// "url": "/live/0551954854",
// "live_ms": 1720428680003,
// "clients": 1,
// "frames": 8431,
// "send_bytes": 66463941,
// "recv_bytes": 89323998,
// "kbps": {
// "recv_30s": 0,
// "send_30s": 0
// },
// "publish": {
// "active": false,
// "cid": "b3op069g"
// },
// "video": null,
// "audio": null
// }]
// }
func (s *Srs) GetStreamStatus(id string) (bool, error) {
type Stream struct {
Id string `json:"id"`
Name string `json:"name"`
Publish struct {
Active bool `json:"active"`
Cid string `json:"cid"`
} `json:"publish"`
}
res := struct {
Code int `json:"code"`
Streams []Stream `json:"streams"`
}{}
if err := apiRequest(s.Ctx, s.Schema+"://"+s.Addr+"/api/v1/streams?count=99", nil, &res); err != nil {
return false, errors.Wrapf(err, "api/v1/stream")
}
if len(res.Streams) == 0 {
return false, nil
} else {
for _, v := range res.Streams {
if v.Name == id {
return v.Publish.Active, nil
}
}
}
return false, nil
}
func (s *Srs) GetAddr() string {
return s.Addr
}
func (s *Srs) GetWebRTCAddr(id string) string {
return "webrtc://" + s.Addr + "/live/" + id
}
+59
View File
@@ -0,0 +1,59 @@
package media
import (
"context"
"github.com/ossrs/go-oryx-lib/errors"
)
type Zlm struct {
Ctx context.Context
Schema string // The schema of ZLM, eg: http
Addr string // The address of ZLM, eg: localhost:8085
Secret string // The secret of ZLM, eg: ZLMediaKit_secret
}
// /index/api/openRtpServer
// secret={{ZLMediaKit_secret}}&port=0&enable_tcp=1&stream_id=test2
func (z *Zlm) Publish(id, ssrc string) (int, error) {
res := struct {
Code int `json:"code"`
Port int `json:"port"`
}{}
if err := apiRequest(z.Ctx, z.Schema+"://"+z.Addr+"/index/api/openRtpServer?secret="+z.Secret+"&port=0&enable_tcp=1&stream_id="+id+"&ssrc="+ssrc, nil, &res); err != nil {
return 0, errors.Wrapf(err, "gb/v1/publish")
}
return res.Port, nil
}
// /index/api/closeRtpServer
func (z *Zlm) Unpublish(id string) error {
res := struct {
Code int `json:"code"`
}{}
if err := apiRequest(z.Ctx, z.Schema+"://"+z.Addr+"/index/api/closeRtpServer?secret="+z.Secret+"&stream_id="+id, nil, &res); err != nil {
return errors.Wrapf(err, "gb/v1/publish")
}
return nil
}
// /index/api/getMediaList
func (z *Zlm) GetStreamStatus(id string) (bool, error) {
res := struct {
Code int `json:"code"`
}{}
if err := apiRequest(z.Ctx, z.Schema+"://"+z.Addr+"/index/api/getMediaList?secret="+z.Secret+"&stream_id="+id, nil, &res); err != nil {
return false, errors.Wrapf(err, "gb/v1/publish")
}
return res.Code == 0, nil
}
func (z *Zlm) GetAddr() string {
return z.Addr
}
func (z *Zlm) GetWebRTCAddr(id string) string {
return "http://" + z.Addr + "/index/api/webrtc?app=rtp&stream=" + id + "&type=play"
}