golang实现SDP会话描述协议解析与生成的插件库sdpRFC4566的使用
Golang实现SDP会话描述协议解析与生成的插件库sdpRFC4566的使用
简介
Package sdp实现了SDP: Session Description Protocol [RFC4566]。作为gortc核心包,符合gortc原则。
示例
SDP示例
v=0
o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
s=SDP Seminar
i=A Seminar on the session description protocol
u=http://www.example.com/seminars/sdp.pdf
e=j.doe@example.com (Jane Doe)
p=12345
c=IN IP4 224.2.17.12/127
b=CT:154798
t=2873397496 2873404696
r=7d 1h 0 25h
k=clear:ab8c4df8b8f4as8v8iuy8re
a=recvonly
m=audio 49170 RTP/AVP 0
m=video 51372 RTP/AVP 99
b=AS:66781
k=prompt
a=rtpmap:99 h263-1998/90000
编码示例
package main
import (
"fmt"
"net"
"time"
"gortc.io/sdp"
)
func main() {
var (
s sdp.Session
b []byte
)
// 定义媒体
audio := sdp.Media{
Description: sdp.MediaDescription{
Type: "audio",
Port: 49170,
Formats: []string{"0"},
Protocol: "RTP/AVP",
},
}
video := sdp.Media{
Description: sdp.MediaDescription{
Type: "video",
Port: 51372,
Formats: []string{"99"},
Protocol: "RTP/AVP",
},
Bandwidths: sdp.Bandwidths{
sdp.BandwidthApplicationSpecific: 66781,
},
Encryption: sdp.Encryption{
Method: "prompt",
},
}
video.AddAttribute("rtpmap", "99", "h263-1998/90000")
// 定义消息
m := &sdp.Message{
Origin: sdp.Origin{
Username: "jdoe",
SessionID: 2890844526,
SessionVersion: 2890842807,
Address: "10.47.16.5",
},
Name: "SDP Seminar",
Info: "A Seminar on the session description protocol",
URI: "http://www.example.com/seminars/sdp.pdf",
Email: "j.doe@example.com (Jane Doe)",
Phone: "12345",
Connection: sdp.ConnectionData{
IP: net.ParseIP("224.2.17.12"),
TTL: 127,
},
Bandwidths: sdp.Bandwidths{
sdp.BandwidthConferenceTotal: 154798,
},
Timing: []sdp.Timing{
{
Start: sdp.NTPToTime(2873397496),
End: sdp.NTPToTime(2873404696),
Repeat: 7 * time.Hour * 24,
Active: 3600 * time.Second,
Offsets: []time.Duration{
0,
25 * time.Hour,
},
},
},
Encryption: sdp.Encryption{
Method: "clear",
Key: "ab8c4df8b8f4as8v8iuy8re",
},
Medias: []sdp.Media{audio, video},
}
m.AddFlag("recvonly")
// 将消息添加到会话
s = m.Append(s)
// 将会话追加到字节缓冲区
b = s.AppendTo(b)
fmt.Println(string(b))
}
解码示例
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"gortc.io/sdp"
)
func main() {
name := "example.sdp"
if len(os.Args) > 1 {
name = os.Args[1]
}
var (
s sdp.Session
b []byte
err error
f io.ReadCloser
)
fmt.Println("sdp file:", name)
if f, err = os.Open(name); err != nil {
log.Fatal("err:", err)
}
defer f.Close()
if b, err = ioutil.ReadAll(f); err != nil {
log.Fatal("err:", err)
}
if s, err = sdp.DecodeSession(b, s); err != nil {
log.Fatal("err:", err)
}
for k, v := range s {
fmt.Println(k, v)
}
d := sdp.NewDecoder(s)
m := new(sdp.Message)
if err = d.Decode(m); err != nil {
log.Fatal("err:", err)
}
fmt.Println("Decoded session", m.Name)
fmt.Println("Info:", m.Info)
fmt.Println("Origin:", m.Origin)
}
直接使用Session结构
package main
import (
"fmt"
"gortc.io/sdp"
)
func main() {
var (
s sdp.Session
b []byte
)
b = s.AddVersion(0).
AddMediaDescription(sdp.MediaDescription{
Type: "video",
Port: 51372,
Formats: []string{"99"},
Protocol: "RTP/AVP",
}).
AddAttribute("rtpmap", "99", "h263-1998/90000").
AddLine(sdp.TypeEmail, "test@test.com").
AddRaw('ü', "vαlue").
AppendTo(b)
// 等等
fmt.Println(string(b))
// 输出:
// v=0
// m=video 51372 RTP/AVP 99
// a=rtpmap:99 h263-1998/90000
// e=test@test.com
// ü=vαlue
}
支持的参数
- [x] v (协议版本)
- [x] o (发起者和会话标识符)
- [x] s (会话名称)
- [x] i (会话信息)
- [x] u (描述URI)
- [x] e (电子邮件地址)
- [x] p (电话号码)
- [x] c (连接信息)
- [x] b (零个或多个带宽信息行)
- [x] t (时间)
- [x] r (重复)
- [x] z (时区调整)
- [x] k (加密密钥)
- [x] a (零个或多个会话属性行)
- [x] m (媒体名称和传输地址)
构建状态
许可证
更多关于golang实现SDP会话描述协议解析与生成的插件库sdpRFC4566的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现SDP会话描述协议解析与生成的插件库sdpRFC4566的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang实现SDP协议解析与生成的插件库
SDP(会话描述协议)是一种用于描述多媒体会话的协议,常用于WebRTC、VoIP等应用中。在Go语言中,我们可以使用sdp
库来解析和生成符合RFC4566标准的SDP数据。
安装sdp库
go get github.com/notedit/sdp
基本用法
解析SDP
package main
import (
"fmt"
"github.com/notedit/sdp"
)
func main() {
sdpStr := `v=0
o=- 0 0 IN IP4 127.0.0.1
s=-
c=IN IP4 127.0.0.1
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=sendrecv
m=video 51372 RTP/AVP 99
a=rtpmap:99 H264/90000
a=fmtp:99 profile-level-id=42e01f;packetization-mode=1
a=sendrecv`
// 解析SDP
session, err := sdp.ParseSDP(sdpStr)
if err != nil {
panic(err)
}
// 打印基本信息
fmt.Printf("Version: %d\n", session.Version)
fmt.Printf("Origin: %s\n", session.Origin)
fmt.Printf("SessionName: %s\n", session.SessionName)
fmt.Printf("Connection: %s\n", session.Connection)
// 遍历媒体流
for _, media := range session.Medias {
fmt.Printf("\nMedia: %s %d %s\n", media.Type, media.Port, media.Protocol)
for _, attr := range media.Attributes {
fmt.Printf("Attribute: %s=%s\n", attr.Key, attr.Value)
}
}
}
生成SDP
package main
import (
"fmt"
"github.com/notedit/sdp"
)
func main() {
// 创建新的SDP会话
session := &sdp.Session{
Version: 0,
Origin: sdp.Origin{
Username: "-",
SessionID: 1234567890,
SessionVersion: 1234567890,
NetType: "IN",
AddrType: "IP4",
UnicastAddress: "127.0.0.1",
},
SessionName: "Go SDP Example",
Connection: &sdp.Connection{
NetType: "IN",
AddrType: "IP4",
ConnectionAddr: "127.0.0.1",
},
Time: &sdp.Time{
StartTime: 0,
StopTime: 0,
},
}
// 添加音频媒体流
audioMedia := &sdp.Media{
Type: "audio",
Port: 49170,
Protocol: "RTP/AVP",
Formats: []string{"0"},
Attributes: []*sdp.Attribute{
{Key: "rtpmap", Value: "0 PCMU/8000"},
{Key: "sendrecv"},
},
}
session.Medias = append(session.Medias, audioMedia)
// 添加视频媒体流
videoMedia := &sdp.Media{
Type: "video",
Port: 51372,
Protocol: "RTP/AVP",
Formats: []string{"99"},
Attributes: []*sdp.Attribute{
{Key: "rtpmap", Value: "99 H264/90000"},
{Key: "fmtp", Value: "99 profile-level-id=42e01f;packetization-mode=1"},
{Key: "sendrecv"},
},
}
session.Medias = append(session.Medias, videoMedia)
// 生成SDP字符串
sdpStr := session.String()
fmt.Println(sdpStr)
}
高级功能
处理ICE候选
// 添加ICE候选
audioMedia.AddAttribute("candidate", "1 1 UDP 2130706431 192.168.1.100 5000 typ host")
audioMedia.AddAttribute("candidate", "2 1 UDP 1694498815 203.0.113.1 5000 typ srflx raddr 192.168.1.100 rport 5000")
处理DTLS指纹
session.AddAttribute("fingerprint", "sha-256 12:DF:3A:...")
处理SSRC
videoMedia.AddAttribute("ssrc", "12345678 cname:user@example.com")
实际应用示例
以下是一个完整的WebRTC SDP生成示例:
func generateWebRTCSDP() string {
session := &sdp.Session{
Version: 0,
Origin: sdp.Origin{
Username: "-",
SessionID: uint64(time.Now().UnixNano()),
SessionVersion: uint64(time.Now().UnixNano()),
NetType: "IN",
AddrType: "IP4",
UnicastAddress: "127.0.0.1",
},
SessionName: "WebRTC",
Connection: &sdp.Connection{
NetType: "IN",
AddrType: "IP4",
ConnectionAddr: "0.0.0.0",
},
Time: &sdp.Time{
StartTime: 0,
StopTime: 0,
},
}
// 添加音频媒体
audio := &sdp.Media{
Type: "audio",
Port: 9, // 使用端口9表示不指定端口
Protocol: "UDP/TLS/RTP/SAVPF",
Formats: []string{"111", "103", "104", "9", "0", "8", "106", "105", "13", "110", "112", "113", "126"},
Attributes: []*sdp.Attribute{
{Key: "rtpmap", Value: "111 opus/48000/2"},
{Key: "fmtp", Value: "111 minptime=10;useinbandfec=1"},
{Key: "rtpmap", Value: "103 ISAC/16000"},
{Key: "rtpmap", Value: "104 ISAC/32000"},
{Key: "rtpmap", Value: "9 G722/8000"},
{Key: "rtpmap", Value: "0 PCMU/8000"},
{Key: "rtpmap", Value: "8 PCMA/8000"},
{Key: "rtpmap", Value: "106 CN/32000"},
{Key: "rtpmap", Value: "105 CN/16000"},
{Key: "rtpmap", Value: "13 CN/8000"},
{Key: "rtpmap", Value: "110 telephone-event/48000"},
{Key: "rtpmap", Value: "112 telephone-event/32000"},
{Key: "rtpmap", Value: "113 telephone-event/16000"},
{Key: "rtpmap", Value: "126 telephone-event/8000"},
{Key: "ssrc", Value: "12345678 cname:audio"},
{Key: "ssrc", Value: "12345678 msid:audio audio_label"},
{Key: "ssrc", Value: "12345678 mslabel:audio_label"},
{Key: "sendrecv"},
},
}
session.Medias = append(session.Medias, audio)
// 添加视频媒体
video := &sdp.Media{
Type: "video",
Port: 9,
Protocol: "UDP/TLS/RTP/SAVPF",
Formats: []string{"100", "101", "102", "125", "107", "108", "109", "127", "124", "120", "123", "119", "114", "115", "116", "117", "118"},
Attributes: []*sdp.Attribute{
{Key: "rtpmap", Value: "100 VP8/90000"},
{Key: "rtpmap", Value: "101 VP9/90000"},
{Key: "rtpmap", Value: "102 H264/90000"},
{Key: "fmtp", Value: "102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"},
{Key: "rtpmap", Value: "125 H264/90000"},
{Key: "fmtp", Value: "125 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f"},
{Key: "rtpmap", Value: "107 H264/90000"},
{Key: "fmtp", Value: "107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f"},
{Key: "rtpmap", Value: "108 H264/90000"},
{Key: "fmtp", Value: "108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f"},
{Key: "rtpmap", Value: "109 rtx/90000"},
{Key: "fmtp", Value: "109 apt=100"},
{Key: "rtpmap", Value: "127 rtx/90000"},
{Key: "fmtp", Value: "127 apt=101"},
{Key: "rtpmap", Value: "124 rtx/90000"},
{Key: "fmtp", Value: "124 apt=102"},
{Key: "rtpmap", Value: "120 rtx/90000"},
{Key: "fmtp", Value: "120 apt=125"},
{Key: "rtpmap", Value: "123 rtx/90000"},
{Key: "fmtp", Value: "123 apt=107"},
{Key: "rtpmap", Value: "119 rtx/90000"},
{Key: "fmtp", Value: "119 apt=108"},
{Key: "ssrc", Value: "23456789 cname:video"},
{Key: "ssrc", Value: "23456789 msid:video video_label"},
{Key: "ssrc", Value: "23456789 mslabel:video_label"},
{Key: "sendrecv"},
},
}
session.Medias = append(session.Medias, video)
// 添加全局属性
session.AddAttribute("group", "BUNDLE audio video")
session.AddAttribute("ice-ufrag", "abcdefgh")
session.AddAttribute("ice-pwd", "1234567890abcdefghijklmnopqrstuv")
session.AddAttribute("fingerprint", "sha-256 12:DF:3A:...")
session.AddAttribute("setup", "actpass")
return session.String()
}
总结
sdp
库提供了完整的SDP协议解析和生成功能,可以方便地用于WebRTC、VoIP等多媒体应用中。通过这个库,我们可以:
- 解析标准的SDP字符串为结构化的Go对象
- 通过Go对象生成符合RFC4566标准的SDP字符串
- 方便地添加和修改SDP的各个部分
- 支持WebRTC等现代协议扩展
在实际应用中,可以根据需要扩展或封装这个库,以满足特定的业务需求。