基于HTML与Java的简易在线会议系统实现
基于HTML与Java的简易在线会议系统实现
概述
实现一个类似腾讯会议基本功能的演示系统,包含视频会议、屏幕共享、文字聊天等核心功能。这个实现使用HTML作为前端界面,Java作为后端服务,WebRTC技术实现实时通信。
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>简易在线会议系统</title><style>:root {--primary-color: #2d8cf0;--secondary-color: #19be6b;--danger-color: #ed4014;--dark-color: #17233d;--light-color: #f8f8f9;}* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #2d8cf0);color: var(--light-color);min-height: 100vh;padding: 20px;}.container {max-width: 1400px;margin: 0 auto;display: flex;flex-direction: column;height: 95vh;}header {text-align: center;padding: 20px;background: rgba(23, 35, 61, 0.8);border-radius: 12px;margin-bottom: 20px;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);}h1 {font-size: 2.5rem;margin-bottom: 10px;background: linear-gradient(90deg, #fff, #2d8cf0);-webkit-background-clip: text;-webkit-text-fill-color: transparent;}.subtitle {font-size: 1.1rem;opacity: 0.9;}.main-content {display: flex;flex: 1;gap: 20px;}.video-section {flex: 3;display: flex;flex-direction: column;background: rgba(23, 35, 61, 0.8);border-radius: 12px;padding: 20px;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);}.video-container {display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 20px;flex: 1;margin-bottom: 20px;}.video-item {background: #1a1f2d;border-radius: 8px;overflow: hidden;position: relative;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);}.video-item video {width: 100%;height: 100%;object-fit: cover;background: #000;}.user-info {position: absolute;bottom: 0;left: 0;right: 0;background: rgba(0, 0, 0, 0.7);padding: 8px 12px;font-size: 0.9rem;}.controls {display: flex;justify-content: center;gap: 15px;padding: 15px;background: rgba(23, 35, 61, 0.9);border-radius: 8px;}.control-btn {width: 60px;height: 60px;border-radius: 50%;border: none;background: var(--dark-color);color: white;font-size: 1.5rem;cursor: pointer;display: flex;align-items: center;justify-content: center;transition: all 0.3s ease;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);}.control-btn:hover {transform: translateY(-3px);box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);}.control-btn.active {background: var(--primary-color);}.control-btn.end-call {background: var(--danger-color);}.control-btn.end-call:hover {background: #c5300c;}.side-panel {flex: 1;display: flex;flex-direction: column;gap: 20px;}.participants {background: rgba(23, 35, 61, 0.8);border-radius: 12px;padding: 20px;flex: 1;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);}.participants h2 {margin-bottom: 15px;font-size: 1.3rem;color: var(--primary-color);padding-bottom: 10px;border-bottom: 1px solid rgba(255, 255, 255, 0.1);}.participant-list {list-style: none;max-height: 300px;overflow-y: auto;}.participant-list li {padding: 10px 15px;background: rgba(255, 255, 255, 0.05);margin-bottom: 8px;border-radius: 6px;display: flex;align-items: center;}.participant-list li:before {content: "•";color: var(--secondary-color);font-size: 1.5rem;margin-right: 10px;}.chat {background: rgba(23, 35, 61, 0.8);border-radius: 12px;padding: 20px;flex: 2;display: flex;flex-direction: column;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);}.chat h2 {margin-bottom: 15px;font-size: 1.3rem;color: var(--primary-color);padding-bottom: 10px;border-bottom: 1px solid rgba(255, 255, 255, 0.1);}.chat-messages {flex: 1;overflow-y: auto;margin-bottom: 15px;padding: 10px;background: rgba(0, 0, 0, 0.2);border-radius: 6px;}.message {margin-bottom: 12px;padding: 8px 12px;border-radius: 6px;background: rgba(45, 140, 240, 0.2);}.message.self {background: rgba(25, 190, 107, 0.2);text-align: right;}.message-sender {font-weight: bold;font-size: 0.9rem;margin-bottom: 4px;color: var(--primary-color);}.message.self .message-sender {color: var(--secondary-color);}.chat-input {display: flex;gap: 10px;}.chat-input input {flex: 1;padding: 12px 15px;border: none;border-radius: 6px;background: rgba(255, 255, 255, 0.1);color: white;font-size: 1rem;}.chat-input input:focus {outline: none;background: rgba(255, 255, 255, 0.15);}.chat-input button {padding: 12px 20px;border: none;border-radius: 6px;background: var(--primary-color);color: white;cursor: pointer;transition: background 0.3s;}.chat-input button:hover {background: #1a7ad9;}footer {text-align: center;padding: 20px;margin-top: 20px;font-size: 0.9rem;opacity: 0.8;}.meeting-id {display: flex;justify-content: center;gap: 10px;margin: 15px 0;}.meeting-id span {background: rgba(255, 255, 255, 0.1);padding: 8px 15px;border-radius: 6px;font-family: monospace;}@media (max-width: 900px) {.main-content {flex-direction: column;}.video-container {grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));}}</style>
</head>
<body><div class="container"><header><h1>简易在线会议系统</h1><p class="subtitle">使用HTML前端 + Java后端实现类似腾讯会议功能</p><div class="meeting-id"><div>会议ID: <span>852-741-963</span></div><div>参会人数: <span>4</span></div></div></header><div class="main-content"><div class="video-section"><div class="video-container"><div class="video-item"><video id="localVideo" autoplay muted></video><div class="user-info">我 (主持人)</div></div><div class="video-item"><video id="remoteVideo1" autoplay></video><div class="user-info">张工程师</div></div><div class="video-item"><video id="remoteVideo2" autoplay></video><div class="user-info">李设计师</div></div><div class="video-item"><video id="remoteVideo3" autoplay></video><div class="user-info">王产品经理</div></div></div><div class="controls"><button class="control-btn active" id="micToggle">🎤</button><button class="control-btn active" id="cameraToggle">📷</button><button class="control-btn" id="screenShare">🖥️</button><button class="control-btn end-call" id="endCall">📞</button></div></div><div class="side-panel"><div class="participants"><h2>参会人员 (4)</h2><ul class="participant-list"><li>我 (主持人)</li><li>张工程师</li><li>李设计师</li><li>王产品经理</li></ul></div><div class="chat"><h2>会议聊天</h2><div class="chat-messages"><div class="message"><div class="message-sender">系统消息</div><div>欢迎使用简易会议系统!会议已开始</div></div><div class="message"><div class="message-sender">张工程师</div><div>大家能听到我说话吗?</div></div><div class="message self"><div class="message-sender">我</div><div>可以听到,声音很清晰</div></div><div class="message"><div class="message-sender">李设计师</div><div>我共享一下设计稿,大家看看</div></div><div class="message"><div class="message-sender">王产品经理</div><div>这个功能需要在下周三前完成</div></div></div><div class="chat-input"><input type="text" id="messageInput" placeholder="输入消息..."><button id="sendMessage">发送</button></div></div></div></div><footer><p>简易在线会议系统 | HTML + Java + WebRTC 实现 | © 2023 会议技术演示</p></footer></div><script>// 模拟WebRTC功能document.addEventListener('DOMContentLoaded', function() {const micToggle = document.getElementById('micToggle');const cameraToggle = document.getElementById('cameraToggle');const screenShare = document.getElementById('screenShare');const endCall = document.getElementById('endCall');const messageInput = document.getElementById('messageInput');const sendMessage = document.getElementById('sendMessage');const chatMessages = document.querySelector('.chat-messages');// 模拟视频流navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {const localVideo = document.getElementById('localVideo');localVideo.srcObject = stream;}).catch(err => {console.error('访问媒体设备失败:', err);});// 模拟远程视频流const remoteVideos = [document.getElementById('remoteVideo1'),document.getElementById('remoteVideo2'),document.getElementById('remoteVideo3')];// 模拟远程视频流setTimeout(() => {remoteVideos.forEach(video => {video.srcObject = document.getElementById('localVideo').srcObject;});}, 1000);// 麦克风控制micToggle.addEventListener('click', function() {this.classList.toggle('active');console.log('麦克风状态:', this.classList.contains('active') ? '开启' : '关闭');});// 摄像头控制cameraToggle.addEventListener('click', function() {this.classList.toggle('active');const localVideo = document.getElementById('localVideo');localVideo.srcObject.getVideoTracks()[0].enabled = this.classList.contains('active');console.log('摄像头状态:', this.classList.contains('active') ? '开启' : '关闭');});// 屏幕共享screenShare.addEventListener('click', function() {console.log('屏幕共享功能已启动');alert('屏幕共享功能已启动(模拟)');this.classList.add('active');// 模拟屏幕共享const screenShareElement = document.createElement('div');screenShareElement.innerHTML = `<div style="position:absolute; top:20px; right:20px; width:300px; height:200px; background:#000; border:2px solid #2d8cf0; border-radius:8px; overflow:hidden; z-index:100;"><div style="position:absolute; top:0; left:0; right:0; background:#2d8cf0; color:white; padding:5px; font-size:12px;">屏幕共享中</div><div style="display:flex; align-items:center; justify-content:center; height:100%; color:#aaa;">屏幕共享内容</div></div>`;document.body.appendChild(screenShareElement);});// 结束通话endCall.addEventListener('click', function() {if (confirm('确定要结束会议吗?')) {console.log('会议已结束');alert('会议已结束,即将关闭页面(模拟)');// 在实际应用中,这里会关闭所有媒体流并断开连接}});// 发送消息sendMessage.addEventListener('click', function() {const message = messageInput.value.trim();if (message) {addMessage('我', message, true);messageInput.value = '';// 模拟回复if (message.toLowerCase().includes('你好')) {setTimeout(() => {addMessage('张工程师', '你好!会议进行得怎么样?', false);}, 1000);}}});// 按回车发送消息messageInput.addEventListener('keypress', function(e) {if (e.key === 'Enter') {sendMessage.click();}});function addMessage(sender, text, isSelf) {const messageElement = document.createElement('div');messageElement.classList.add('message');if (isSelf) messageElement.classList.add('self');messageElement.innerHTML = `<div class="message-sender">${sender}</div><div>${text}</div>`;chatMessages.appendChild(messageElement);chatMessages.scrollTop = chatMessages.scrollHeight;}});</script>
</body>
</html>
技术实现说明
前端实现 (HTML/JavaScript)
-
用户界面:
- 视频会议区域(本地和远程视频)
- 控制面板(麦克风、摄像头、屏幕共享、结束会议)
- 参会人员列表
- 文字聊天功能
-
核心功能:
- 使用WebRTC API实现音视频通信
getUserMedia
获取摄像头和麦克风权限RTCPeerConnection
建立对等连接RTCDataChannel
实现文字聊天功能- 屏幕共享功能(使用
getDisplayMedia
)
后端实现 (Java)
-
信令服务器:
- 使用Spring Boot构建WebSocket服务器
- 处理客户端之间的信令交换(SDP/ICE)
- 房间管理(创建/加入/离开会议)
-
主要功能:
// 示例:WebSocket信令处理 @ServerEndpoint("/signaling") public class SignalingEndpoint {@OnOpenpublic void onOpen(Session session) {// 新连接建立}@OnMessagepublic void onMessage(String message, Session session) {// 处理信令消息:offer/answer/candidate}@OnClosepublic void onClose(Session session) {// 连接关闭处理} }// 示例:会议管理 @RestController @RequestMapping("/api/meeting") public class MeetingController {@PostMapping("/create")public ResponseEntity<String> createMeeting() {// 创建新会议,返回会议ID}@PostMapping("/join")public ResponseEntity<String> joinMeeting(@RequestParam String meetingId) {// 加入指定会议} }
-
媒体服务器:
- 使用Kurento或Mediasoup处理多人会议中的媒体流转发
- 实现SFU架构,减轻客户端压力
系统架构
前端 (HTML/JS) ││ WebSocket▼
Java后端 (Spring Boot)││ 信令交换▼
WebRTC P2P连接 / 媒体服务器
关键功能实现
-
视频会议:
- 使用WebRTC建立点对点连接
- 使用STUN/TURN服务器解决NAT穿透问题
-
屏幕共享:
- 使用
navigator.mediaDevices.getDisplayMedia()
获取屏幕流 - 将屏幕流添加到RTCPeerConnection中
- 使用
-
文字聊天:
- 使用RTCDataChannel实现点对点聊天
- 或通过WebSocket服务器转发消息
-
会议管理:
- 后端维护会议房间状态
- 处理用户加入/离开事件
部署与扩展
-
部署要求:
- HTTPS环境(WebRTC要求)
- STUN/TURN服务器
- 媒体服务器(用于多人会议)
-
扩展功能:
- 会议录制
- 虚拟背景
- 会议白板
- 文件共享
- 会议控制(静音、踢人)
以上实现展示了使用HTML和Java构建在线会议系统的基本架构和核心功能。实际开发中还需要考虑网络优化、安全性、错误处理等更多细节问题。