mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-07-13 00:21:10 +08:00
音视频通话
This commit is contained in:
parent
e6451179d6
commit
4b9412f685
17
config/livekit.yaml
Normal file
17
config/livekit.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
port: 7880
|
||||||
|
rtc:
|
||||||
|
tcp_port: 7881
|
||||||
|
port_range_start: 50000
|
||||||
|
port_range_end: 60000
|
||||||
|
use_external_ip: true
|
||||||
|
|
||||||
|
redis:
|
||||||
|
address: redis:6379
|
||||||
|
password: openIM123
|
||||||
|
|
||||||
|
# LiveKit 要求 API secret 至少 32 字符;生产环境请替换为强随机串并与 openim-rpc-rtc.yml 中 apiSecret 一致
|
||||||
|
keys:
|
||||||
|
devkey: openim-livekit-default-secret-32chars-min
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level: info
|
||||||
@ -18,14 +18,14 @@ prometheus:
|
|||||||
|
|
||||||
liveKit:
|
liveKit:
|
||||||
# LiveKit server address reachable from the RTC service (internal/backend address)
|
# LiveKit server address reachable from the RTC service (internal/backend address)
|
||||||
# Example: http://livekit:7880
|
# When deployed via docker-compose, use the service name 'livekit'
|
||||||
internalAddress: http://localhost:7880
|
internalAddress: http://livekit:7880
|
||||||
# LiveKit server address reachable from clients (external/public address)
|
# LiveKit server address reachable from clients (external/public address)
|
||||||
# Example: wss://livekit.example.com
|
# Production should use wss://livekit.example.com with TLS
|
||||||
externalAddress: ws://localhost:7880
|
externalAddress: ws://192.168.1.91:7880
|
||||||
# LiveKit API key (configured in your LiveKit server)
|
# LiveKit API key (configured in your LiveKit server)
|
||||||
apiKey: devkey
|
apiKey: devkey
|
||||||
# LiveKit API secret (configured in your LiveKit server)
|
# LiveKit API secret(须 ≥32 字符,须与 config/livekit.yaml keys 中对应值一致)
|
||||||
apiSecret: secret
|
apiSecret: openim-livekit-default-secret-32chars-min
|
||||||
# Token expiry in seconds (default: 3600 = 1 hour)
|
# Token expiry in seconds (default: 3600 = 1 hour)
|
||||||
tokenExpiry: 3600
|
tokenExpiry: 3600
|
||||||
|
|||||||
@ -163,6 +163,24 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- openim
|
- openim
|
||||||
|
|
||||||
|
livekit:
|
||||||
|
image: "${LIVEKIT_IMAGE:-livekit/livekit-server:latest}"
|
||||||
|
container_name: livekit
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "7880:7880"
|
||||||
|
- "7881:7881"
|
||||||
|
- "50000-50100:50000-50100/udp"
|
||||||
|
volumes:
|
||||||
|
- ./config/livekit.yaml:/etc/livekit.yaml
|
||||||
|
command: --config /etc/livekit.yaml --node-ip=0.0.0.0
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
environment:
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
networks:
|
||||||
|
- openim
|
||||||
|
|
||||||
minio:
|
minio:
|
||||||
image: "${MINIO_IMAGE}"
|
image: "${MINIO_IMAGE}"
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@ -108,3 +108,7 @@ func (p *PrometheusDiscoveryApi) MessageGateway(c *gin.Context) {
|
|||||||
func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
|
||||||
p.discovery(c, prommetrics.MessageTransferKeyName)
|
p.discovery(c, prommetrics.MessageTransferKeyName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PrometheusDiscoveryApi) Rtc(c *gin.Context) {
|
||||||
|
p.discovery(c, p.config.Share.RpcRegisterName.Rtc)
|
||||||
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/openimsdk/protocol/group"
|
"github.com/openimsdk/protocol/group"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
"github.com/openimsdk/protocol/relation"
|
"github.com/openimsdk/protocol/relation"
|
||||||
|
"github.com/openimsdk/protocol/rtc"
|
||||||
"github.com/openimsdk/protocol/third"
|
"github.com/openimsdk/protocol/third"
|
||||||
"github.com/openimsdk/protocol/user"
|
"github.com/openimsdk/protocol/user"
|
||||||
|
|
||||||
@ -103,6 +104,10 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
rtcConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Rtc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||||
@ -301,6 +306,20 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
|||||||
captchaGroup.POST("/verify", cp.VerifyCaptcha)
|
captchaGroup.POST("/verify", cp.VerifyCaptcha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
rc := NewRtcApi(rtc.NewRtcServiceClient(rtcConn))
|
||||||
|
rtcGroup := r.Group("/rtc")
|
||||||
|
rtcGroup.POST("/signal_message_assemble", rc.SignalMessageAssemble)
|
||||||
|
rtcGroup.POST("/signal_get_room_by_group_id", rc.SignalGetRoomByGroupID)
|
||||||
|
rtcGroup.POST("/signal_get_token_by_room_id", rc.SignalGetTokenByRoomID)
|
||||||
|
rtcGroup.POST("/signal_get_rooms", rc.SignalGetRooms)
|
||||||
|
rtcGroup.POST("/get_signal_invitation_info", rc.GetSignalInvitationInfo)
|
||||||
|
rtcGroup.POST("/get_signal_invitation_info_start_app", rc.GetSignalInvitationInfoStartApp)
|
||||||
|
rtcGroup.POST("/signal_send_custom_signal", rc.SignalSendCustomSignal)
|
||||||
|
rtcGroup.POST("/get_signal_invitation_records", rc.GetSignalInvitationRecords)
|
||||||
|
rtcGroup.POST("/delete_signal_records", rc.DeleteSignalRecords)
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
statisticsGroup := r.Group("/statistics")
|
statisticsGroup := r.Group("/statistics")
|
||||||
statisticsGroup.POST("/user/register", u.UserRegisterCount)
|
statisticsGroup.POST("/user/register", u.UserRegisterCount)
|
||||||
@ -330,6 +349,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
|||||||
proDiscoveryGroup.GET("/push", pd.Push)
|
proDiscoveryGroup.GET("/push", pd.Push)
|
||||||
proDiscoveryGroup.GET("/msg_gateway", pd.MessageGateway)
|
proDiscoveryGroup.GET("/msg_gateway", pd.MessageGateway)
|
||||||
proDiscoveryGroup.GET("/msg_transfer", pd.MessageTransfer)
|
proDiscoveryGroup.GET("/msg_transfer", pd.MessageTransfer)
|
||||||
|
proDiscoveryGroup.GET("/rtc", pd.Rtc)
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|||||||
65
internal/api/rtc.go
Normal file
65
internal/api/rtc.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright © 2024 OpenIM. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/openimsdk/protocol/rtc"
|
||||||
|
"github.com/openimsdk/tools/a2r"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RtcApi struct {
|
||||||
|
Client rtc.RtcServiceClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRtcApi(client rtc.RtcServiceClient) RtcApi {
|
||||||
|
return RtcApi{Client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) SignalMessageAssemble(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.SignalMessageAssemble, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) SignalGetRoomByGroupID(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.SignalGetRoomByGroupID, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) SignalGetTokenByRoomID(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.SignalGetTokenByRoomID, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) SignalGetRooms(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.SignalGetRooms, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) GetSignalInvitationInfo(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.GetSignalInvitationInfo, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) GetSignalInvitationInfoStartApp(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.GetSignalInvitationInfoStartApp, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) SignalSendCustomSignal(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.SignalSendCustomSignal, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) GetSignalInvitationRecords(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.GetSignalInvitationRecords, o.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *RtcApi) DeleteSignalRecords(c *gin.Context) {
|
||||||
|
a2r.Call(c, rtc.RtcServiceClient.DeleteSignalRecords, o.Client)
|
||||||
|
}
|
||||||
@ -32,7 +32,7 @@ import (
|
|||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mcontext"
|
"github.com/openimsdk/tools/mcontext"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SignalMessageAssemble processes a signal request from the WebSocket gateway
|
// SignalMessageAssemble processes a signal request from the WebSocket gateway
|
||||||
@ -379,8 +379,8 @@ func (s *rtcServer) SignalSendCustomSignal(ctx context.Context, req *rtc.SignalS
|
|||||||
if uid == opUserID {
|
if uid == opUserID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := s.sendSignalingNotification(ctx, opUserID, uid, int32(constant.SingleChatType), nil, content); err != nil {
|
if err := s.sendCustomSignalNotification(ctx, opUserID, uid, int32(constant.SingleChatType), content); err != nil {
|
||||||
log.ZWarn(ctx, "sendSignalingNotification customSignal failed", err, "to", uid)
|
log.ZWarn(ctx, "sendCustomSignalNotification failed", err, "to", uid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &rtc.SignalSendCustomSignalResp{}, nil
|
return &rtc.SignalSendCustomSignalResp{}, nil
|
||||||
@ -462,10 +462,28 @@ func (s *rtcServer) sendSignalingNotification(ctx context.Context, sendID, recvI
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalSignalReq serialises a SignalReq to JSON bytes using protojson,
|
// sendCustomSignalNotification sends a CustomSignalNotification (1605) to a user.
|
||||||
// which correctly handles protobuf oneof fields for client-side parsing.
|
func (s *rtcServer) sendCustomSignalNotification(ctx context.Context, sendID, recvID string, sessionType int32, content []byte) error {
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
msgData := &sdkws.MsgData{
|
||||||
|
SendID: sendID,
|
||||||
|
RecvID: recvID,
|
||||||
|
SessionType: sessionType,
|
||||||
|
ContentType: int32(constant.CustomSignalNotification),
|
||||||
|
MsgFrom: int32(constant.SysMsgType),
|
||||||
|
Content: content,
|
||||||
|
CreateTime: now,
|
||||||
|
SendTime: now,
|
||||||
|
ServerMsgID: uuid.New().String(),
|
||||||
|
ClientMsgID: uuid.New().String(),
|
||||||
|
Options: make(map[string]bool),
|
||||||
|
}
|
||||||
|
_, err := s.msgClient.MsgClient.SendMsg(ctx, &pbmsg.SendMsgReq{MsgData: msgData})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func marshalSignalReq(req *rtc.SignalReq) []byte {
|
func marshalSignalReq(req *rtc.SignalReq) []byte {
|
||||||
b, _ := protojson.Marshal(req)
|
b, _ := proto.Marshal(req)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ serviceBinaries:
|
|||||||
openim-rpc-group: 1
|
openim-rpc-group: 1
|
||||||
openim-rpc-friend: 1
|
openim-rpc-friend: 1
|
||||||
openim-rpc-msg: 1
|
openim-rpc-msg: 1
|
||||||
|
openim-rpc-rtc: 1
|
||||||
openim-rpc-third: 1
|
openim-rpc-third: 1
|
||||||
toolBinaries:
|
toolBinaries:
|
||||||
- check-free-memory
|
- check-free-memory
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user