# 语音/视频通话模块说明 ## 📋 模块概述 本模块实现了基于 WebRTC 的一对一语音/视频通话功能,支持通话邀请、接听、拒绝、取消、结束等完整流程,并提供通话记录管理功能。 **实现时间**: 已完成 **技术方案**: WebRTC + WebSocket 信令交换 **完成度**: 100% --- ## 🏗️ 架构设计 ### 核心组件 1. **CallRecord** - 通话记录实体类 - 路径: `crmeb-common/src/main/java/com/zbkj/common/model/call/CallRecord.java` - 功能: 存储通话记录信息(通话双方、类型、状态、时长等) 2. **CallService** - 通话业务逻辑服务 - 路径: `crmeb-service/src/main/java/com/zbkj/service/service/impl/CallServiceImpl.java` - 功能: 处理通话创建、接听、拒绝、取消、结束等业务逻辑 3. **CallController** - 通话接口控制器 - 路径: `crmeb-front/src/main/java/com/zbkj/front/controller/CallController.java` - 功能: 提供 RESTful API 接口 4. **CallSignalingHandler** - WebRTC 信令处理器 - 路径: `crmeb-front/src/main/java/com/zbkj/front/websocket/CallSignalingHandler.java` - 功能: 处理 WebSocket 信令交换(offer、answer、ice-candidate) --- ## 📊 数据库设计 ### 表名: `eb_call_record` | 字段名 | 类型 | 说明 | |--------|------|------| | id | BIGINT | 主键ID | | call_id | VARCHAR(64) | 通话唯一标识(用于信令) | | caller_id | INT | 主叫用户ID | | callee_id | INT | 被叫用户ID | | call_type | VARCHAR(20) | 通话类型: voice-语音, video-视频 | | status | VARCHAR(20) | 通话状态 | | call_time | DATETIME | 通话发起时间 | | connect_time | DATETIME | 通话接通时间 | | end_time | DATETIME | 通话结束时间 | | duration | INT | 通话时长(秒) | | end_reason | VARCHAR(50) | 结束原因 | | caller_deleted | TINYINT(1) | 主叫是否删除记录 | | callee_deleted | TINYINT(1) | 被叫是否删除记录 | | create_time | DATETIME | 创建时间 | | update_time | DATETIME | 更新时间 | ### 通话状态说明 - `calling` - 呼叫中(主叫发起,等待被叫响应) - `ringing` - 响铃中(被叫收到邀请) - `connected` - 通话中(双方已接通) - `ended` - 已结束(正常结束) - `missed` - 未接(超时未接听) - `rejected` - 已拒绝(被叫拒绝) - `cancelled` - 已取消(主叫取消) - `busy` - 忙线(对方正在通话中) --- ## 🔌 API 接口 ### 1. 发起通话 ```http POST /api/front/call/initiate Content-Type: application/json { "calleeId": 123, "callType": "video" // voice 或 video } ``` **响应**: ```json { "code": 200, "msg": "操作成功", "data": { "callId": "call_abc123...", "callType": "video", "calleeId": 123, "calleeName": "用户昵称", "calleeAvatar": "头像URL", "status": "calling", "signalingUrl": "/ws/call/call_abc123..." } } ``` ### 2. 接听通话 ```http POST /api/front/call/accept/{callId} ``` ### 3. 拒绝通话 ```http POST /api/front/call/reject/{callId} ``` ### 4. 取消通话 ```http POST /api/front/call/cancel/{callId} ``` ### 5. 结束通话 ```http POST /api/front/call/end/{callId}?endReason=normal ``` ### 6. 获取通话记录 ```http GET /api/front/call/history?page=1&limit=20 ``` ### 7. 删除通话记录 ```http DELETE /api/front/call/record/{recordId} ``` ### 8. 获取未接来电数量 ```http GET /api/front/call/missed/count ``` ### 9. 检查通话状态 ```http GET /api/front/call/status ``` ### 10. 获取通话详情 ```http GET /api/front/call/detail/{callId} ``` --- ## 🔄 WebSocket 信令协议 ### 连接地址 ``` ws://your-domain/ws/call ``` ### 客户端发送消息类型 #### 1. 注册用户 ```json { "type": "register", "userId": 123 } ``` #### 2. 发起通话请求 ```json { "type": "call_request", "calleeId": 456, "callType": "video" } ``` #### 3. 接听通话 ```json { "type": "call_accept", "callId": "call_abc123..." } ``` #### 4. 拒绝通话 ```json { "type": "call_reject", "callId": "call_abc123..." } ``` #### 5. 取消通话 ```json { "type": "call_cancel", "callId": "call_abc123..." } ``` #### 6. 结束通话 ```json { "type": "call_end", "callId": "call_abc123...", "reason": "normal" } ``` #### 7. WebRTC Offer ```json { "type": "offer", "callId": "call_abc123...", "sdp": { "type": "offer", "sdp": "v=0\r\no=..." } } ``` #### 8. WebRTC Answer ```json { "type": "answer", "callId": "call_abc123...", "sdp": { "type": "answer", "sdp": "v=0\r\no=..." } } ``` #### 9. ICE Candidate ```json { "type": "ice-candidate", "callId": "call_abc123...", "candidate": { "candidate": "candidate:...", "sdpMLineIndex": 0, "sdpMid": "0" } } ``` ### 服务端推送消息类型 #### 1. 注册成功 ```json { "type": "registered", "userId": 123 } ``` #### 2. 来电通知 ```json { "type": "incoming_call", "callId": "call_abc123...", "callerId": 123, "callerName": "用户昵称", "callerAvatar": "头像URL", "callType": "video" } ``` #### 3. 通话已创建 ```json { "type": "call_created", "callId": "call_abc123..." } ``` #### 4. 对方已接听 ```json { "type": "call_accepted", "callId": "call_abc123..." } ``` #### 5. 对方已拒绝 ```json { "type": "call_rejected", "callId": "call_abc123..." } ``` #### 6. 对方已取消 ```json { "type": "call_cancelled", "callId": "call_abc123..." } ``` #### 7. 通话已结束 ```json { "type": "call_ended", "callId": "call_abc123...", "reason": "normal" } ``` #### 8. 通话超时 ```json { "type": "call_timeout", "callId": "call_abc123..." } ``` #### 9. 错误消息 ```json { "type": "error", "message": "错误描述" } ``` --- ## 🎯 通话流程 ### 语音/视频通话完整流程 ``` 主叫方 服务器 被叫方 | | | |--1. 发起通话----------->| | | POST /call/initiate | | | | | |<--返回callId-----------| | | | | |--2. 连接WebSocket----->| | | register | | | | | | |--3. 推送来电通知------->| | | incoming_call | | | | | |<--4. 接听通话----------| | | call_accept | | | | |<--5. 通知已接听--------|--5. 通知已接听-------->| | call_accepted | call_accepted | | | | |--6. 发送Offer--------->|--6. 转发Offer--------->| | | | |<--7. 接收Answer--------|<--7. 发送Answer--------| | | | |--8. 交换ICE候选------->|--8. 转发ICE候选------->| |<-----------------------|<-----------------------| | | | |========== WebRTC P2P 通话建立 =================| | | | |--9. 结束通话---------->| | | call_end | | | |--9. 通知结束---------->| | | call_ended | ``` --- ## ⚙️ 核心功能特性 ### 1. 通话管理 - ✅ 发起语音/视频通话 - ✅ 接听/拒绝/取消通话 - ✅ 通话中状态检测 - ✅ 通话时长统计 - ✅ 通话记录保存 ### 2. 状态管理 - ✅ 用户在线状态检测 - ✅ 通话状态实时同步 - ✅ 忙线检测(防止重复呼叫) - ✅ 超时自动挂断(60秒) ### 3. 信令交换 - ✅ WebSocket 长连接 - ✅ SDP Offer/Answer 交换 - ✅ ICE Candidate 交换 - ✅ 信令自动转发 ### 4. 通话记录 - ✅ 通话历史查询 - ✅ 未接来电统计 - ✅ 双向软删除 - ✅ 通话详情查看 ### 5. 异常处理 - ✅ 网络断开自动结束 - ✅ 超时自动挂断 - ✅ 错误消息推送 - ✅ 状态一致性保证 --- ## 🔒 安全特性 1. **权限验证**: 所有接口需要登录认证 2. **操作权限**: 只能操作自己参与的通话 3. **状态校验**: 严格的状态机转换验证 4. **防重复呼叫**: 检测用户是否正在通话中 5. **超时保护**: 60秒超时自动结束未接通的通话 --- ## 📱 客户端集成指南 ### 1. 发起通话 ```javascript // 1. 调用 API 发起通话 const response = await fetch('/api/front/call/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ calleeId: 456, callType: 'video' }) }); const { callId, signalingUrl } = await response.json(); // 2. 连接 WebSocket const ws = new WebSocket('ws://your-domain/ws/call'); // 3. 注册用户 ws.send(JSON.stringify({ type: 'register', userId: currentUserId })); // 4. 创建 WebRTC 连接 const pc = new RTCPeerConnection(config); // 5. 添加本地媒体流 const stream = await navigator.mediaDevices.getUserMedia({ video: callType === 'video', audio: true }); stream.getTracks().forEach(track => pc.addTrack(track, stream)); // 6. 创建并发送 Offer const offer = await pc.createOffer(); await pc.setLocalDescription(offer); ws.send(JSON.stringify({ type: 'offer', callId: callId, sdp: offer })); // 7. 监听 ICE Candidate pc.onicecandidate = (event) => { if (event.candidate) { ws.send(JSON.stringify({ type: 'ice-candidate', callId: callId, candidate: event.candidate })); } }; // 8. 接收远程流 pc.ontrack = (event) => { remoteVideo.srcObject = event.streams[0]; }; ``` ### 2. 接听通话 ```javascript // 1. 收到来电通知 ws.onmessage = async (event) => { const msg = JSON.parse(event.data); if (msg.type === 'incoming_call') { // 显示来电界面 showIncomingCallUI(msg); } }; // 2. 用户点击接听 async function acceptCall(callId) { // 调用接听 API await fetch(`/api/front/call/accept/${callId}`, { method: 'POST' }); // 创建 WebRTC 连接 const pc = new RTCPeerConnection(config); // 添加本地媒体流 const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); stream.getTracks().forEach(track => pc.addTrack(track, stream)); // 监听 Offer ws.onmessage = async (event) => { const msg = JSON.parse(event.data); if (msg.type === 'offer') { await pc.setRemoteDescription(msg.sdp); const answer = await pc.createAnswer(); await pc.setLocalDescription(answer); // 发送 Answer ws.send(JSON.stringify({ type: 'answer', callId: callId, sdp: answer })); } if (msg.type === 'ice-candidate') { await pc.addIceCandidate(msg.candidate); } }; } ``` --- ## 🧪 测试建议 ### 功能测试 1. 正常通话流程测试 2. 拒绝/取消通话测试 3. 超时未接测试 4. 忙线检测测试 5. 通话记录查询测试 ### 异常测试 1. 网络断开重连测试 2. 对方离线测试 3. 并发呼叫测试 4. WebSocket 断开测试 ### 性能测试 1. 并发通话数量测试 2. 信令延迟测试 3. 内存泄漏测试 --- ## 📝 注意事项 1. **WebRTC 兼容性**: 确保客户端浏览器支持 WebRTC 2. **HTTPS 要求**: WebRTC 需要在 HTTPS 环境下运行(本地开发除外) 3. **STUN/TURN 服务器**: 生产环境需要配置 STUN/TURN 服务器用于 NAT 穿透 4. **媒体权限**: 需要用户授权摄像头和麦克风权限 5. **超时时间**: 默认 60 秒超时,可根据需求调整 6. **通话记录清理**: 建议定期清理过期的通话记录 --- ## 🚀 后续优化建议 1. **群组通话**: 支持多人视频会议 2. **屏幕共享**: 支持屏幕共享功能 3. **通话质量**: 添加网络质量检测和自适应码率 4. **通话录制**: 支持通话录制功能 5. **美颜滤镜**: 集成美颜和滤镜功能 6. **通话统计**: 添加通话质量统计和分析 --- **文档版本**: v1.0 **最后更新**: 2024年12月26日 **维护状态**: ✅ 已完成