new female
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3m36s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3m36s
				
			This commit is contained in:
		
							parent
							
								
									3a8257df5b
								
							
						
					
					
						commit
						fa7c5b7c7a
					
				| @ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 | |||||||
| on: | on: | ||||||
|   push: |   push: | ||||||
|     branches: |     branches: | ||||||
|       - 'new_male' |       - 'new_female' | ||||||
| 
 | 
 | ||||||
| env: | env: | ||||||
|   BUILD: staging |   BUILD: staging | ||||||
| @ -30,15 +30,15 @@ jobs: | |||||||
|         uses: https://gitea.yantootech.com/neil/build-push-action@v6 |         uses: https://gitea.yantootech.com/neil/build-push-action@v6 | ||||||
|         with: |         with: | ||||||
|           push: false |           push: false | ||||||
|           tags: emotion-digital-video:${{ gitea.run_id }} |           tags: emotion-female-digital-video:${{ gitea.run_id }} | ||||||
|       - name: Run docker |       - name: Run docker | ||||||
|         run: | |         run: | | ||||||
|           pwd |           pwd | ||||||
|           if [ "$(docker ps -q -f name=^emotion-digital-video$)" ]; then |           if [ "$(docker ps -q -f name=^emotion-female-digital-video$)" ]; then | ||||||
|             docker stop emotion-digital-video |             docker stop emotion-female-digital-video | ||||||
|           fi |           fi | ||||||
|           docker run -d --rm --name emotion-digital-video \ |           docker run -d --rm --name emotion-female-digital-video \ | ||||||
|             -v /usr/share/fonts/opentype/noto:/usr/share/fonts \ |             -v /usr/share/fonts/opentype/noto:/usr/share/fonts \ | ||||||
|             -p 6900:3000 \ |             -p 6901:3000 \ | ||||||
|             emotion-digital-video:${{ gitea.run_id }} |             emotion-female-digital-video:${{ gitea.run_id }} | ||||||
|       - run: echo "🍏 This job's status is ${{ job.status }}." |       - run: echo "🍏 This job's status is ${{ job.status }}." | ||||||
							
								
								
									
										20
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								server.js
									
									
									
									
									
								
							| @ -122,24 +122,24 @@ let currentSceneIndex = 0; | |||||||
| const scenes = [ | const scenes = [ | ||||||
|   { |   { | ||||||
|     name: '起床', |     name: '起床', | ||||||
|     defaultVideo: 'qc-bd-4.mp4', |     defaultVideo: '8-5-qc-bd-female.mp4', | ||||||
|     interactionVideo: 'qc-sh-4.mp4', |     interactionVideo: '8-5-qc-sh-female.mp4', | ||||||
|     tag: 'wakeup', |     tag: 'wakeup', | ||||||
|     apiKey: 'bot-20250724150616-xqpz8' // 起床场景的API key
 |     apiKey: 'bot-20250730213756-l627w' // 起床场景的API key
 | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: '开车', |     name: '走路', | ||||||
|     defaultVideo: 'kc-bd-3.mp4', |     defaultVideo: '8-5-sb-bd-female.mp4', | ||||||
|     interactionVideo: 'kc-sh-3.mp4', |     interactionVideo: '8-5-sb-sh-female.mp4', | ||||||
|     tag: 'driving', |     tag: 'driving', | ||||||
|     apiKey: 'bot-20250623140339-r8f8b' // 开车场景的API key
 |     apiKey: 'bot-20250703161810-sgkrh' // 开车场景的API key
 | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: '喝茶', |     name: '喝茶', | ||||||
|     defaultVideo: 'hc-bd-3.mp4', |     defaultVideo: '8-5-hc-bd-female.mp4', | ||||||
|     interactionVideo: 'hc-sh-3(1).mp4', |     interactionVideo: '8-5-hc-sh-female.mp4', | ||||||
|     tag: 'tea', |     tag: 'tea', | ||||||
|     apiKey: 'bot-20250804180724-4dgtk' // 喝茶场景的API key
 |     apiKey: 'bot-20250805140055-ccdr6' // 喝茶场景的API key
 | ||||||
|   } |   } | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ export const config = { | |||||||
|   // LLM API配置
 |   // LLM API配置
 | ||||||
|   llm: { |   llm: { | ||||||
|     apiKey: 'd012651b-a65b-4b13-8ff3-cc4ff3a29783', // 请替换为实际的API密钥
 |     apiKey: 'd012651b-a65b-4b13-8ff3-cc4ff3a29783', // 请替换为实际的API密钥
 | ||||||
|     model: 'bot-20250724150616-xqpz8', |     model: 'bot-20250730213756-l627w', | ||||||
|   }, |   }, | ||||||
|    |    | ||||||
|   // Minimaxi API配置
 |   // Minimaxi API配置
 | ||||||
| @ -16,7 +16,7 @@ export const config = { | |||||||
|   audio: { |   audio: { | ||||||
|     model: 'speech-02-hd', |     model: 'speech-02-hd', | ||||||
|     voiceSetting: { |     voiceSetting: { | ||||||
|       voice_id: 'yantu-qinggang-demo2-male-4', |       voice_id: 'yantu-qinggang-3', | ||||||
|       speed: 1, |       speed: 1, | ||||||
|       vol: 1, |       vol: 1, | ||||||
|       pitch: 0, |       pitch: 0, | ||||||
| @ -110,4 +110,4 @@ export function getAudioConfig() { | |||||||
|     audioSetting: config.audio.audioSetting, |     audioSetting: config.audio.audioSetting, | ||||||
|     ...config.system, |     ...config.system, | ||||||
|   }; |   }; | ||||||
| }  | }  | ||||||
|  | |||||||
							
								
								
									
										510
									
								
								src/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								src/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,510 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="zh-CN"> | ||||||
|  | <head> | ||||||
|  |     <meta charset="UTF-8"> | ||||||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | ||||||
|  |     <title>Soulmate In Parallels - 壹和零人工智能</title> | ||||||
|  |     <link rel="stylesheet" href="styles.css"> | ||||||
|  |     <link rel="icon" type="image/png" sizes="48x48" href="favicon.png" /> | ||||||
|  |     <style> | ||||||
|  |         /* 全屏视频样式 */ | ||||||
|  |         * { | ||||||
|  |             margin: 0; | ||||||
|  |             padding: 0; | ||||||
|  |             box-sizing: border-box; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         html, body { | ||||||
|  |             height: 100%; | ||||||
|  |             overflow: hidden; | ||||||
|  |             background: linear-gradient(135deg, #87CEEB 0%, #B0E0E6 100%); /* 浅蓝色渐变背景 */ | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .container { | ||||||
|  |             width: 100vw; | ||||||
|  |             height: 100vh; | ||||||
|  |             margin: 0; | ||||||
|  |             padding: 0; | ||||||
|  |             display: flex; | ||||||
|  |             flex-direction: column; | ||||||
|  |             position: relative; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .main-content { | ||||||
|  |             flex: 1; | ||||||
|  |             background: transparent; | ||||||
|  |             border-radius: 0; | ||||||
|  |             padding: 0; | ||||||
|  |             box-shadow: none; | ||||||
|  |             width: 100%; | ||||||
|  |             height: 100%; | ||||||
|  |             display: flex; | ||||||
|  |             flex-direction: column; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .recorded-video-section { | ||||||
|  |             flex: 1; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             width: 100%; | ||||||
|  |             height: 100%; | ||||||
|  |             position: relative; | ||||||
|  |             /* 确保视频区域固定高度并居中 */ | ||||||
|  |             min-height: 100vh; | ||||||
|  |             max-height: 100vh; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 视频容器样式 - 支持双缓冲,固定9:16比例 */ | ||||||
|  |         .video-container { | ||||||
|  |             position: relative; | ||||||
|  |             width: 56.25vh; /* 9:16比例,与视频宽度保持一致 */ | ||||||
|  |             height: 100vh; | ||||||
|  |             overflow: hidden; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             margin: 0 auto; /* 水平居中 */ | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #recordedVideo, #recordedVideoBuffer { | ||||||
|  |             position: absolute; | ||||||
|  |             width: 56.25vh; /* 9:16比例,高度为100vh时,宽度为100vh * 9/16 = 56.25vh */ | ||||||
|  |             height: 100vh; | ||||||
|  |             object-fit: cover; | ||||||
|  |             border-radius: 0; | ||||||
|  |             box-shadow: none; | ||||||
|  |             transition: opacity 0.5s ease-in-out; | ||||||
|  |             /* 确保视频始终居中 */ | ||||||
|  |             left: 50%; | ||||||
|  |             top: 50%; | ||||||
|  |             transform: translate(-50%, -50%); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 主视频默认显示 */ | ||||||
|  |         #recordedVideo { | ||||||
|  |             opacity: 1; | ||||||
|  |             z-index: 2; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 缓冲视频默认隐藏 */ | ||||||
|  |         #recordedVideoBuffer { | ||||||
|  |             opacity: 0; | ||||||
|  |             z-index: 1; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 切换状态 */ | ||||||
|  |         #recordedVideo.switching { | ||||||
|  |             opacity: 0; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #recordedVideoBuffer.switching { | ||||||
|  |             opacity: 1; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 加载状态 */ | ||||||
|  |         .video-loading { | ||||||
|  |             position: absolute; | ||||||
|  |             top: 50%; | ||||||
|  |             left: 50%; | ||||||
|  |             transform: translate(-50%, -50%); | ||||||
|  |             z-index: 10; | ||||||
|  |             color: white; | ||||||
|  |             font-size: 18px; | ||||||
|  |             opacity: 0; | ||||||
|  |             transition: opacity 0.3s ease; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .video-loading.show { | ||||||
|  |             opacity: 1; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 加载动画 */ | ||||||
|  |         .loading-spinner { | ||||||
|  |             width: 40px; | ||||||
|  |             height: 40px; | ||||||
|  |             border: 3px solid rgba(255, 255, 255, 0.3); | ||||||
|  |             border-top: 3px solid white; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             animation: spin 1s linear infinite; | ||||||
|  |             margin: 0 auto 10px; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         @keyframes spin { | ||||||
|  |             0% { transform: rotate(0deg); } | ||||||
|  |             100% { transform: rotate(360deg); } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 响应式设计 - 确保在不同屏幕尺寸下视频容器保持9:16比例 */ | ||||||
|  |         @media (max-width: 768px) { | ||||||
|  |             .video-container { | ||||||
|  |                 height: 100vh; | ||||||
|  |                 width: 56.25vh; /* 9:16比例,与视频宽度保持一致 */ | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             #recordedVideo, #recordedVideoBuffer { | ||||||
|  |                 width: 56.25vh; /* 9:16比例 */ | ||||||
|  |                 height: 100vh; | ||||||
|  |                 object-fit: cover; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         @media (min-width: 769px) { | ||||||
|  |             .video-container { | ||||||
|  |                 height: 100vh; | ||||||
|  |                 width: 56.25vh; /* 9:16比例,与视频宽度保持一致 */ | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             #recordedVideo, #recordedVideoBuffer { | ||||||
|  |                 width: 56.25vh; /* 9:16比例 */ | ||||||
|  |                 height: 100vh; | ||||||
|  |                 object-fit: cover; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 横屏模式优化 */ | ||||||
|  |         @media (orientation: landscape) and (max-height: 500px) { | ||||||
|  |             .video-container { | ||||||
|  |                 height: 100vh; | ||||||
|  |                 width: 56.25vh; /* 9:16比例,与视频宽度保持一致 */ | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             .controls { | ||||||
|  |                 bottom: 20px; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 竖屏模式优化 */ | ||||||
|  |         @media (orientation: portrait) { | ||||||
|  |             .video-container { | ||||||
|  |                 height: 100vh; | ||||||
|  |                 width: 56.25vh; /* 9:16比例,与视频宽度保持一致 */ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .controls { | ||||||
|  |             position: absolute; | ||||||
|  |             bottom: 50px; | ||||||
|  |             left: 50%; | ||||||
|  |             transform: translateX(-50%); | ||||||
|  |             z-index: 10; | ||||||
|  |             display: flex !important; | ||||||
|  |             flex-direction: row !important; | ||||||
|  |             justify-content: center; | ||||||
|  |             align-items: center; | ||||||
|  |             gap: 20px; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /* 确保移动端也保持同一行 */ | ||||||
|  |         @media (max-width: 768px) { | ||||||
|  |             .controls { | ||||||
|  |                 flex-direction: row !important; | ||||||
|  |                 gap: 15px; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton { | ||||||
|  |             width: 60px; | ||||||
|  |             height: 60px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             background: rgba(34, 197, 94, 0.9); | ||||||
|  |             backdrop-filter: blur(10px); | ||||||
|  |             border: none; | ||||||
|  |             cursor: pointer; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             transition: all 0.3s ease; | ||||||
|  |             box-shadow: 0 4px 15px rgba(34, 197, 94, 0.3); | ||||||
|  |             min-width: auto; | ||||||
|  |             padding: 15px 30px; | ||||||
|  |             font-size: 1.1rem; | ||||||
|  |             border-radius: 25px; | ||||||
|  |             min-width: 200px; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton:hover:not(:disabled) { | ||||||
|  |             background: rgba(22, 163, 74, 0.95); | ||||||
|  |             transform: scale(1.1); | ||||||
|  |             box-shadow: 0 6px 20px rgba(34, 197, 94, 0.5); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton.connecting { | ||||||
|  |             background: rgba(255, 193, 7, 0.9); | ||||||
|  |             cursor: not-allowed; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton.connecting:hover { | ||||||
|  |             background: rgba(255, 193, 7, 0.9); | ||||||
|  |             transform: none; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton.calling { | ||||||
|  |             background: rgba(255, 193, 7, 0.9); | ||||||
|  |             animation: pulse 2s infinite; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton.calling:hover { | ||||||
|  |             background: rgba(255, 193, 7, 0.95); | ||||||
|  |             transform: scale(1.05); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         @keyframes pulse { | ||||||
|  |             0% { | ||||||
|  |                 box-shadow: 0 4px 15px rgba(255, 193, 7, 0.3); | ||||||
|  |             } | ||||||
|  |             50% { | ||||||
|  |                 box-shadow: 0 6px 25px rgba(255, 193, 7, 0.6); | ||||||
|  |             } | ||||||
|  |             100% { | ||||||
|  |                 box-shadow: 0 4px 15px rgba(255, 193, 7, 0.3); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .audio-status { | ||||||
|  |             position: absolute; | ||||||
|  |             top: 20px; | ||||||
|  |             left: 50%; | ||||||
|  |             transform: translateX(-50%); | ||||||
|  |             background: rgba(0, 0, 0, 0.7); | ||||||
|  |             color: white; | ||||||
|  |             padding: 8px 16px; | ||||||
|  |             border-radius: 20px; | ||||||
|  |             font-size: 14px; | ||||||
|  |             z-index: 1000; | ||||||
|  |             transition: all 0.3s ease; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .audio-status.connecting { | ||||||
|  |             background: rgba(255, 193, 7, 0.9); | ||||||
|  |             color: #000; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .audio-status.connected { | ||||||
|  |             background: rgba(40, 167, 69, 0.9); | ||||||
|  |             color: white; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         .audio-status.error { | ||||||
|  |             background: rgba(220, 53, 69, 0.9); | ||||||
|  |             color: white; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton svg { | ||||||
|  |             width: 24px; | ||||||
|  |             height: 24px; | ||||||
|  |             fill: white; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #startButton:disabled { | ||||||
|  |             opacity: 0.5; | ||||||
|  |             cursor: not-allowed; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #stopButton { | ||||||
|  |             width: 60px; | ||||||
|  |             height: 60px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             background: rgba(220, 53, 69, 0.9); | ||||||
|  |             backdrop-filter: blur(10px); | ||||||
|  |             border: none; | ||||||
|  |             cursor: pointer; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             transition: all 0.3s ease; | ||||||
|  |             box-shadow: 0 4px 15px rgba(220, 53, 69, 0.3); | ||||||
|  |             padding: 0; /* 确保没有内边距影响居中 */ | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #stopButton:hover:not(:disabled) { | ||||||
|  |             background: rgba(200, 35, 51, 0.95); | ||||||
|  |             transform: scale(1.1); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #stopButton svg { | ||||||
|  |             width: 24px; | ||||||
|  |             height: 24px; | ||||||
|  |             display: block; /* 确保SVG作为块级元素 */ | ||||||
|  |             margin: auto; /* 额外的居中保证 */ | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #stopButton:disabled { | ||||||
|  |             opacity: 0.5; | ||||||
|  |             cursor: not-allowed; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* 头像样式 - 确保显示 */ | ||||||
|  |         .avatar-container { | ||||||
|  |             position: absolute; | ||||||
|  |             top: 50%; | ||||||
|  |             left: 50%; | ||||||
|  |             transform: translate(-50%, -50%); | ||||||
|  |             z-index: 15; /* 提高z-index确保在视频上方 */ | ||||||
|  |             display: flex; | ||||||
|  |             flex-direction: column; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             transition: opacity 0.3s ease; | ||||||
|  |             opacity: 1; /* 确保默认显示 */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .avatar-container.hidden { | ||||||
|  |             opacity: 0; | ||||||
|  |             pointer-events: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .avatar { | ||||||
|  |             width: 120px; | ||||||
|  |             height: 120px; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             border: 4px solid rgba(255, 255, 255, 0.8); | ||||||
|  |             box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); | ||||||
|  |             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             justify-content: center; | ||||||
|  |             color: white; | ||||||
|  |             font-size: 48px; | ||||||
|  |             font-weight: bold; | ||||||
|  |             overflow: hidden; /* 确保图片不会溢出 */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .avatar img { | ||||||
|  |             width: 100%; | ||||||
|  |             height: 100%; | ||||||
|  |             border-radius: 50%; | ||||||
|  |             object-fit: cover; | ||||||
|  |             display: block; /* 确保图片显示 */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* 确保视频默认隐藏 */ | ||||||
|  |         #recordedVideo, #recordedVideoBuffer { | ||||||
|  |             position: absolute; | ||||||
|  |             width: 56.25vh; | ||||||
|  |             height: 100vh; | ||||||
|  |             object-fit: cover; | ||||||
|  |             border-radius: 0; | ||||||
|  |             box-shadow: none; | ||||||
|  |             transition: opacity 0.5s ease-in-out; | ||||||
|  |             left: 50%; | ||||||
|  |             top: 50%; | ||||||
|  |             transform: translate(-50%, -50%); | ||||||
|  |             opacity: 0; /* 默认隐藏视频 */ | ||||||
|  |             z-index: 1; /* 确保在头像下方 */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* 通话时隐藏头像,显示视频 */ | ||||||
|  |         .video-container.calling .avatar-container { | ||||||
|  |             opacity: 0; | ||||||
|  |             pointer-events: none; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .video-container.calling #recordedVideo { | ||||||
|  |             opacity: 1; | ||||||
|  |             z-index: 10; | ||||||
|  |         } | ||||||
|  |     </style> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div class="container"> | ||||||
|  |         <!-- 隐藏的header --> | ||||||
|  |         <header style="display: none;"> | ||||||
|  |             <h1>WebRTC 音频通话</h1> | ||||||
|  |             <p>实时播放录制视频,支持文本和语音输入</p> | ||||||
|  |         </header> | ||||||
|  | 
 | ||||||
|  |         <div class="main-content"> | ||||||
|  |             <!-- 音频状态显示 - 完全隐藏 --> | ||||||
|  |             <div class="audio-status" style="display: none;"> | ||||||
|  |                 <div class="status-indicator"> | ||||||
|  |                     <span id="audioStatus" style="display: none;">未连接</span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <!-- 录制视频播放区域 - 全屏显示 --> | ||||||
|  |             <div class="recorded-video-section"> | ||||||
|  |                 <div class="video-container" id="videoContainer"> | ||||||
|  |                     <!-- 头像容器 --> | ||||||
|  |                     <div class="avatar-container" id="avatarContainer"> | ||||||
|  |                         <div class="avatar" id="avatar"> | ||||||
|  |                             <!-- 使用相对路径引用图片 --> | ||||||
|  |                             <img src="./tx.png" alt="头像" onerror="this.style.display='none'; this.parentElement.innerHTML='AI';"> | ||||||
|  |                         </div> | ||||||
|  |                         <!-- <div class="avatar-name">AI助手</div> --> | ||||||
|  |                     </div> | ||||||
|  |                      | ||||||
|  |                     <!-- 主视频元素 --> | ||||||
|  |                     <video id="recordedVideo" autoplay muted> | ||||||
|  |                         <source src="" type="video/mp4"> | ||||||
|  |                         您的浏览器不支持视频播放 | ||||||
|  |                     </video> | ||||||
|  |                      | ||||||
|  |                     <!-- 缓冲视频元素 --> | ||||||
|  |                     <video id="recordedVideoBuffer" autoplay muted> | ||||||
|  |                         <source src="" type="video/mp4"> | ||||||
|  |                         您的浏览器不支持视频播放 | ||||||
|  |                     </video> | ||||||
|  |                      | ||||||
|  |                     <!-- 加载指示器 --> | ||||||
|  |                     <div class="video-loading" id="videoLoading"> | ||||||
|  |                         <div class="loading-spinner"></div> | ||||||
|  |                         <div>正在切换视频...</div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                  | ||||||
|  |                 <div class="video-info" style="display: none;"> | ||||||
|  |                     <span id="currentVideoName">未选择视频</span> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <!-- 控制按钮 - 悬浮在视频上方 --> | ||||||
|  |             <div class="controls"> | ||||||
|  |                 <button id="startButton" class="btn btn-primary" title="开始通话"> | ||||||
|  |                     <!-- 默认通话图标 --> | ||||||
|  |                     <svg id="callIcon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||||
|  |                         <path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" fill="white"/> | ||||||
|  |                     </svg> | ||||||
|  |                     <!-- 通话中文字显示(初始隐藏) --> | ||||||
|  |                     <span id="callingText" style="display: none; color: white; font-size: 14px;">正在通话中</span> | ||||||
|  |                 </button> | ||||||
|  |                 <button id="stopButton" class="btn btn-danger" disabled title="结束通话" style="display: none;"> | ||||||
|  |                     <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||||
|  |                         <path d="M19.23 15.26l-2.54-.29c-.61-.07-1.21.14-1.64.57l-1.84 1.84c-2.83-1.44-5.15-3.75-6.59-6.59l1.85-1.85c.43-.43.64-1.03.57-1.64l-.29-2.52c-.12-1.01-.97-1.77-1.99-1.77H5.03c-1.13 0-2.07.94-2 2.07.53 8.54 7.36 15.36 15.89 15.89 1.13.07 2.07-.87 2.07-2v-1.73c.01-1.01-.75-1.86-1.76-1.98z" fill="white"/> | ||||||
|  |                         <line x1="18" y1="6" x2="6" y2="18" stroke="white" stroke-width="2"/> | ||||||
|  |                     </svg> | ||||||
|  |                 </button> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <!-- 隐藏的输入区域 --> | ||||||
|  |             <div class="input-section" style="display: none;"> | ||||||
|  |                 <div class="text-input-group"> | ||||||
|  |                     <input type="text" id="textInput" placeholder="输入文本内容..." /> | ||||||
|  |                     <button id="sendTextButton" class="btn btn-primary">发送文本</button> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <!-- 隐藏的视频选择 --> | ||||||
|  |             <div class="video-selection" style="display: none;"> | ||||||
|  |                 <h3>选择要播放的视频</h3> | ||||||
|  |                 <div id="videoList" class="video-list"> | ||||||
|  |                     <!-- 视频列表将在这里动态生成 --> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             <!-- 隐藏的状态显示 --> | ||||||
|  |             <div class="status-section" style="display: none;"> | ||||||
|  |                 <div id="connectionStatus" class="status" style="display: none;">未连接</div> | ||||||
|  |                 <div id="messageLog" class="message-log"></div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|  |     <!-- 隐藏的视频元素,用于WebRTC连接 --> | ||||||
|  |     <video id="localVideo" autoplay muted playsinline style="display: none;"></video> | ||||||
|  |     <video id="remoteVideo" autoplay playsinline style="display: none;"></video> | ||||||
|  | 
 | ||||||
|  |     <script src="/socket.io/socket.io.js"></script> | ||||||
|  |     <script type="module" src="./index.js"></script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-hc-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-hc-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-hc-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-hc-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-qc-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-qc-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-qc-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-qc-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-sb-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-sb-bd-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								videos/8-5-sb-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								videos/8-5-sb-sh-female.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user