diff --git a/README.md b/README.md index 310a1f3d..e7b6fc9f 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ this is ion golang sdk for ion-sfu - [x] Subscribe from session - [x] Publish webm to session +- [x] Save stream to file - [ ] Publish media device to session -- [ ] Save stream to file - [ ] Support ion cluster diff --git a/client.go b/client.go index f3dbf29f..c74c595c 100644 --- a/client.go +++ b/client.go @@ -26,6 +26,7 @@ type Call struct { // Client a sdk client type Client struct { + ID string pub *Transport sub *Transport cfg WebRTCTransportConfig @@ -49,8 +50,9 @@ type Client struct { } // NewClient create a sdk client -func NewClient(addr string, cfg WebRTCTransportConfig) *Client { +func NewClient(addr, id string, cfg WebRTCTransportConfig) *Client { c := &Client{ + ID: id, signal: NewSignal(addr), cfg: cfg, notify: make(chan struct{}), @@ -178,7 +180,7 @@ func (c *Client) Join(sid string) error { if err != nil { return err } - err = c.signal.Join(sid, offer) + err = c.signal.Join(sid, c.ID, offer) return err } diff --git a/engine.go b/engine.go index 22109ce6..a4019f14 100644 --- a/engine.go +++ b/engine.go @@ -44,7 +44,7 @@ func (e *Engine) AddClient(addr, sid, cid string) *Client { if e.clients[sid] == nil { e.clients[sid] = make(map[string]*Client) } - c := NewClient(addr, e.cfg.WebRTC) + c := NewClient(addr, cid, e.cfg.WebRTC) e.clients[sid][cid] = c e.Unlock() if c == nil { diff --git a/example/simple/README.md b/example/simple/README.md new file mode 100644 index 00000000..465a6be1 --- /dev/null +++ b/example/simple/README.md @@ -0,0 +1,26 @@ +# Simple + +This is a simple example to show: + +* Publishs webm to session +* Subscribe from session and save to disk + +## Quick Start + +### 1 build + +``` +go build main.go +``` + +### 2 use + +``` +# see ./main --help +./main -file /Volumes/vm/media/djrm480p.webm -addr "localhost:8000" -session 'test room' +``` + +### 3 tips + +* people in the same room will see your movie +* you will find ogg and ivf on your disk if others publish streams in the same room diff --git a/example/simple/main.go b/example/simple/main.go new file mode 100644 index 00000000..31ff8274 --- /dev/null +++ b/example/simple/main.go @@ -0,0 +1,98 @@ +package main + +import ( + "flag" + "fmt" + "strings" + + log "github.com/pion/ion-log" + sdk "github.com/pion/ion-sdk-go" + "github.com/pion/webrtc/v3" + "github.com/pion/webrtc/v3/pkg/media" + "github.com/pion/webrtc/v3/pkg/media/ivfwriter" + "github.com/pion/webrtc/v3/pkg/media/oggwriter" +) + +func saveToDisk(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { + codec := track.Codec() + var fileWriter media.Writer + var err error + if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) { + log.Infof("Got Opus track, saving to disk as ogg (48 kHz, 2 channels)") + fileWriter, err = oggwriter.New(fmt.Sprintf("%d_%d.ogg", codec.PayloadType, track.SSRC()), 48000, 2) + } else if strings.EqualFold(codec.MimeType, webrtc.MimeTypeVP8) { + log.Infof("Got VP8 track, saving to disk as ivf") + fileWriter, err = ivfwriter.New(fmt.Sprintf("%d_%d.ivf", codec.PayloadType, track.SSRC())) + } + + if err != nil { + log.Errorf("err=%v", err) + fileWriter.Close() + return + } + + for { + rtpPacket, _, err := track.ReadRTP() + if err != nil { + panic(err) + } + if err := fileWriter.WriteRTP(rtpPacket); err != nil { + panic(err) + } + } +} + +func main() { + // init log + fixByFile := []string{"asm_amd64.s", "proc.go", "icegatherer.go"} + fixByFunc := []string{"AddProducer", "NewClient"} + log.Init("debug", fixByFile, fixByFunc) + + // parse flag + var session, addr, file string + flag.StringVar(&file, "file", "./file.webm", "Path to the file media") + flag.StringVar(&addr, "addr", "localhost:50051", "Ion-sfu grpc addr") + flag.StringVar(&session, "session", "test room", "join session name") + flag.Parse() + + // add stun servers + webrtcCfg := webrtc.Configuration{ + ICEServers: []webrtc.ICEServer{ + webrtc.ICEServer{ + URLs: []string{"stun:stun.stunprotocol.org:3478", "stun:stun.l.google.com:19302"}, + }, + }, + } + + config := sdk.Config{ + Log: log.Config{ + Level: "debug", + }, + WebRTC: sdk.WebRTCTransportConfig{ + Configuration: webrtcCfg, + }, + } + // new sdk engine + e := sdk.NewEngine(addr, config) + + // get a client from engine + c := e.AddClient(addr, session, "client id") + + // subscribe rtp from sessoin + // comment this if you don't need save to file + c.OnTrack = saveToDisk + + // client join a session + err := c.Join(session) + + // publish file to session if needed + if err == nil && file != "" { + err = c.PublishWebm(file) + if err != nil { + log.Errorf("err=%v", err) + } + } else { + log.Errorf("err=%v", err) + } + select {} +} diff --git a/go.mod b/go.mod index c2e9717c..4df64b2a 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( github.com/ebml-go/ebml v0.0.0-20160925193348-ca8851a10894 // indirect github.com/ebml-go/webm v0.0.0-20160924163542-629e38feef2a github.com/petar/GoLLRB v0.0.0-20190514000832-33fb24c13b99 // indirect - github.com/pion/ice/v2 v2.0.14 + github.com/pion/ice/v2 v2.0.15 github.com/pion/ion-log v1.0.0 - github.com/pion/ion-sfu v1.7.8 + github.com/pion/ion-sfu v1.9.1-0.20210212123851-331f8471352c github.com/pion/webrtc/v3 v3.0.4 google.golang.org/grpc v1.35.0 ) diff --git a/go.sum b/go.sum index c5316fa5..c6a96d45 100644 --- a/go.sum +++ b/go.sum @@ -138,6 +138,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= +github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -267,12 +269,16 @@ github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI= github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI= github.com/pion/ice/v2 v2.0.14 h1:FxXxauyykf89SWAtkQCfnHkno6G8+bhRkNguSh9zU+4= github.com/pion/ice/v2 v2.0.14/go.mod h1:wqaUbOq5ObDNU5ox1hRsEst0rWfsKuH1zXjQFEWiZwM= +github.com/pion/ice/v2 v2.0.15 h1:KZrwa2ciL9od8+TUVJiYTNsCW9J5lktBjGwW1MacEnQ= +github.com/pion/ice/v2 v2.0.15/go.mod h1:ZIiVGevpgAxF/cXiIVmuIUtCb3Xs4gCzCbXB6+nFkSI= github.com/pion/interceptor v0.0.9 h1:fk5hTdyLO3KURQsf/+RjMpEm4NE3yeTY9Kh97b5BvwA= github.com/pion/interceptor v0.0.9/go.mod h1:dHgEP5dtxOTf21MObuBAjJeAayPxLUAZjerGH8Xr07c= github.com/pion/ion-log v1.0.0 h1:2lJLImCmfCWCR38hLWsjQfBWe6NFz/htbqiYHwvOP/Q= github.com/pion/ion-log v1.0.0/go.mod h1:jwcla9KoB9bB/4FxYDSRJPcPYSLp5XiUUMnOLaqwl4E= github.com/pion/ion-sfu v1.7.8 h1:5DBi3m1eZVOQBcJiV7GPOWLHY56LpDhIBRa8ZmMhz/k= github.com/pion/ion-sfu v1.7.8/go.mod h1:3VcBm7RSsSzB09HH4g5ka63pVvx7UHI4vL2XNFt1jA8= +github.com/pion/ion-sfu v1.9.1-0.20210212123851-331f8471352c h1:+tg7My3x1JEKhDWNo+o3aza7bBlkKI2v3LdhZnIrCeA= +github.com/pion/ion-sfu v1.9.1-0.20210212123851-331f8471352c/go.mod h1:MKDh4JSLpBA/hFeYAYALb6nYpe6Ruknd3pmxPMbdpM8= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.4 h1:O4vvVqr4DGX63vzmO6Fw9vpy3lfztVWHGCQfyw0ZLSY= @@ -297,6 +303,7 @@ github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRh github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A= github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= +github.com/pion/transport v0.12.1/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= github.com/pion/transport v0.12.2 h1:WYEjhloRHt1R86LhUKjC5y+P52Y11/QqEUalvtzVoys= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA= diff --git a/signal.go b/signal.go index b55551b3..4dd304d8 100644 --- a/signal.go +++ b/signal.go @@ -133,8 +133,8 @@ func (s *Signal) onSignalHandle() error { } } -func (s *Signal) Join(sid string, offer webrtc.SessionDescription) error { - log.Infof("[Signal.Join] sid=%v offer=%v", sid, offer) +func (s *Signal) Join(sid, uid string, offer webrtc.SessionDescription) error { + log.Infof("[Signal.Join] sid=%v uid=%v, offer=%v", sid, uid, offer) marshalled, err := json.Marshal(offer) if err != nil { return err @@ -146,6 +146,7 @@ func (s *Signal) Join(sid string, offer webrtc.SessionDescription) error { Payload: &pb.SignalRequest_Join{ Join: &pb.JoinRequest{ Sid: sid, + Uid: uid, Description: marshalled, }, },