"use strict"; const common_vendor = require("../../common/vendor.js"); const _sfc_main = { name: "IdentityVerify", data() { return { loading: false, responses: [], processedResponses: [], assistantResponse: "", audioTranscript: "", videoPlaying: false, showDebugInfo: false, // 设置为true可以显示调试信息 videoUrl: "http://121.36.251.245:9000/minlong/0a0b3516-e0bb-4f6c-874c-8aaaca9d7f8f.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T135206Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=4a79bc77f80ae7344f339717dbe505a3b152140251a6b2c76c1fd5c047b39c74", // 用于存储AI数字人视频URL showReplayButton: false, cameraStream: null, // 存储摄像头流 cameraError: null, // 存储摄像头错误信息 useMiniProgramCameraComponent: false, // 添加小程序相机组件标志 cameraContext: null, // 添加相机上下文 currentSubtitle: "", subtitles: [ { startTime: 0, // 开始时间(秒) endTime: 5, // 结束时间(秒) text: "你好,我是本次面试的面试官,欢迎参加本公司的线上面试!" }, { startTime: 5, endTime: 13, text: "面试预计需要15分钟,请你提前安排在网络良好、光线亮度合适、且相对安静的环境参加这次面试" }, { startTime: 13, endTime: 20, text: "以免影响本次面试的结果。如果你在面试过程中遇到问题,请与我们的招聘人员联系。" } ], secondVideoSubtitles: [ { startTime: 0, endTime: 10, text: "请结合您的基本信息与过往履历进行简单的自我介绍,并讲一讲您有哪些优势胜任本岗位:" } ], thirdVideoSubtitles: [ { startTime: 0, endTime: 3, text: "在工作中,你如何确保个人防护装备的正确使用?" } ], fourthVideoSubtitles: [ { startTime: 0, endTime: 3, text: "描述一次你与团队合作改善生产流程的经历。" } ], fifthVideoSubtitles: [ { startTime: 0, endTime: 6, text: "你在团队合作中曾遇到过哪些挑战?如何解决团队内部的分歧?" } ], sixthVideoSubtitles: [ { startTime: 0, endTime: 5, text: "您已完成本次面试全部题目,请问您对于这个岗位还有什么想要了解的吗?" } ], showAnswerButton: false, // 控制答题按钮显示 currentVideoIndex: 0, // 当前播放的视频索引 videoList: [ "http://121.36.251.245:9000/minlong/0a0b3516-e0bb-4f6c-874c-8aaaca9d7f8f.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T135206Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=4a79bc77f80ae7344f339717dbe505a3b152140251a6b2c76c1fd5c047b39c74", // 第一段视频 "http://121.36.251.245:9000/minlong/9ab3fd68-a2e9-47a7-a05e-a6e2253ef22c.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T143129Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=7a0ebf1058252b5f76895b31a5293d4781b33ede63d32dce148350846aa20621", // 第二段视频 "http://121.36.251.245:9000/minlong/69406ce9-8d8e-48aa-ba2f-3b12ea5b6a6c.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T144114Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=a43a06217a63f9bb6af975b1a7aa419b6f8e3d77d8c6c9c67d1070edfe60dc43", // 第三段视频 "http://121.36.251.245:9000/minlong/1cd448b2-16ea-4565-be25-2cf71d1bf7b2.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T144554Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=6ef5b0b160feab053e7d95952cdac62266d1a1eb48999efb17d7a3c4e0b495ed", "http://121.36.251.245:9000/minlong/5a9ad6b2-0de8-48e3-8eb7-141a9bee4a9b.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T145623Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=8a2120a4c6b059d64f90620377fdda2536f9fff9c455d5140210ef35990758c6", "http://121.36.251.245:9000/minlong/7aafb07e-ab0d-477e-9124-3263d0b7bf6f.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T145857Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=54ebe67d751c7e44a0f608b26175c9d076685a0e647e7e134cda22bbca2639eb" //结束 ] }; }, mounted() { this.playDigitalHumanVideo(); this.initCamera(); }, beforeDestroy() { this.stopUserCamera(); }, methods: { // 初始化相机 initCamera() { const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay" || systemInfo.uniPlatform === "mp-baidu" || systemInfo.uniPlatform === "mp-toutiao"; this.useMiniProgramCameraComponent = isMiniProgram; if (isMiniProgram) { this.$nextTick(() => { this.cameraContext = common_vendor.index.createCameraContext(); }); } else { this.startUserCamera(); } }, // 启动用户摄像头 async startUserCamera() { try { const systemInfo = common_vendor.index.getSystemInfoSync(); const isMiniProgram = systemInfo.uniPlatform && systemInfo.uniPlatform.startsWith("mp-"); if (isMiniProgram) { console.log("小程序环境不支持 getUserMedia API"); return; } if (!navigator || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { throw new Error("您的浏览器不支持摄像头访问"); } const stream = await navigator.mediaDevices.getUserMedia({ video: { width: { ideal: 200 }, height: { ideal: 150 }, facingMode: "user" // 使用前置摄像头 }, audio: true // 不需要音频 }); this.cameraStream = stream; this.$nextTick(() => { if (this.$refs.userCameraVideo) { this.$refs.userCameraVideo.srcObject = stream; } }); } catch (error) { console.error("无法访问摄像头:", error); this.cameraError = error.message; let errorMessage = "无法访问摄像头,请检查权限设置"; if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") { errorMessage = "摄像头访问被拒绝,请在浏览器设置中允许摄像头访问"; } else if (error.name === "NotFoundError" || error.name === "DevicesNotFoundError") { errorMessage = "未检测到摄像头设备"; } else if (error.name === "NotReadableError" || error.name === "TrackStartError") { errorMessage = "摄像头可能被其他应用占用"; } else if (error.name === "OverconstrainedError") { errorMessage = "摄像头不满足指定的要求"; } else if (error.name === "TypeError" || error.message.includes("SSL")) { errorMessage = "请确保在HTTPS环境下访问"; } common_vendor.index.showToast({ title: errorMessage, icon: "none", duration: 3e3 }); this.handleCameraError(errorMessage); } }, // 停止用户摄像头 stopUserCamera() { if (this.cameraStream) { this.cameraStream.getTracks().forEach((track) => { track.stop(); }); this.cameraStream = null; } }, async fetchData() { this.loading = true; this.assistantResponse = ""; this.audioTranscript = ""; this.processedResponses = []; try { const requestTask = common_vendor.index.request({ url: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", method: "POST", header: { "Content-Type": "application/json", "Authorization": "Bearer sk-9e1ec73a7d97493b8613c63f06b6110c" }, data: { "model": "qwen-omni-turbo", "messages": [ { "role": "user", "content": [ { "type": "input_audio", "input_audio": { "data": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250211/tixcef/cherry.wav", "format": "wav" } }, { "type": "text", "text": "这段音频在说什么" } ] } ], "stream": true, "stream_options": { "include_usage": true }, "modalities": ["text", "audio"], "audio": { "voice": "Cherry", "format": "wav" } }, success: (res) => { console.log("请求成功,响应数据:", res.data); if (typeof res.data === "string" && res.data.includes("data: {")) { const chunks = res.data.split("data: ").filter((chunk) => chunk.trim() !== ""); chunks.forEach((chunk) => { this.handleStreamResponse(chunk); }); } else { this.handleStreamResponse(res.data); } this.playDigitalHumanVideo(); }, fail: (err) => { console.error("请求失败:", err); }, complete: () => { this.loading = false; } }); } catch (error) { console.error("获取数据失败:", error); this.loading = false; } }, handleStreamResponse(data) { if (typeof data === "string") { if (data === "[DONE]") return; try { const cleanData = data.trim(); if (cleanData.startsWith("{") && cleanData.endsWith("}")) { const jsonData = JSON.parse(cleanData); this.processStreamChunk(jsonData); } } catch (e) { console.error("解析JSON失败:", e, "原始数据:", data); } } else { this.processStreamChunk(data); } }, processStreamChunk(chunk) { if (chunk.choices && chunk.choices.length > 0) { const choice = chunk.choices[0]; if (choice.delta && choice.delta.content) { this.assistantResponse += choice.delta.content; } if (choice.delta && choice.delta.audio && choice.delta.audio.transcript) { this.audioTranscript += choice.delta.audio.transcript; } if (choice.delta) { const result = {}; if (choice.delta.role) { result.role = choice.delta.role; } if (choice.delta.audio && choice.delta.audio.transcript) { result.transcript = choice.delta.audio.transcript; } if (Object.keys(result).length > 0) { this.processedResponses.push(result); } } } }, processResponseData() { this.processedResponses = this.responses.map((item) => { const result = {}; if (item.delta && item.delta.role) { result.role = item.delta.role; } if (item.delta && item.delta.audio && item.delta.audio.transcript) { result.transcript = item.delta.audio.transcript; } return result; }).filter((item) => Object.keys(item).length > 0); }, // 播放数字人视频 playDigitalHumanVideo() { this.videoUrl = this.videoList[this.currentVideoIndex]; this.videoPlaying = true; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); setTimeout(() => { if (this.videoPlaying && this.$refs.videoPlayer) { console.log("视频应该正在播放"); } else { console.log("视频可能未成功播放,尝试替代方案"); this.tryAlternativeVideoPath(); } }, 1e3); } else { console.error("无法创建视频上下文"); this.tryAlternativeVideoPath(); } }); }, // 修改 tryAlternativeVideoPath 方法 tryAlternativeVideoPath() { console.log("尝试使用替代路径"); const alternativePaths = [ "./static/demo.mp4", "../static/demo.mp4", "static/demo.mp4", "/static/demo.mp4", // 添加绝对路径 `${window.location.origin}/static/demo.mp4` ]; const currentPathIndex = alternativePaths.indexOf(this.videoUrl); const nextPathIndex = (currentPathIndex + 1) % alternativePaths.length; this.videoUrl = alternativePaths[nextPathIndex]; console.log("尝试新路径:", this.videoUrl); this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.stop(); videoContext.play(); setTimeout(() => { if (nextPathIndex === alternativePaths.length - 1 && !this.videoPlaying) { console.log("所有路径均失败,尝试使用uni.getVideoInfo检查视频"); this.checkVideoWithAPI(); } }, 1e3); } }); }, // 添加新方法:使用uni API检查视频 checkVideoWithAPI() { common_vendor.index.getVideoInfo({ src: "/static/demo.mp4", success: (res) => { console.log("视频信息获取成功:", res); this.videoUrl = "/static/demo.mp4"; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, fail: (err) => { console.error("视频信息获取失败:", err); this.fallbackToLocalVideo(); } }); }, // 添加新方法:回退到本地视频 fallbackToLocalVideo() { console.log("尝试使用本地视频资源"); const platform = common_vendor.index.getSystemInfoSync().platform; if (platform === "android" || platform === "ios") { this.videoUrl = platform === "android" ? "android.resource://package_name/raw/demo" : "file:///assets/demo.mp4"; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); } else { this.videoPlaying = false; common_vendor.index.showToast({ title: "视频加载失败,显示静态图片", icon: "none" }); } }, // 修改 handleVideoError 方法 handleVideoError(e) { console.error("视频加载错误:", e); if (e && e.detail) { console.error("详细错误信息:", e.detail); } common_vendor.index.getFileInfo({ filePath: this.videoUrl.startsWith("/") ? this.videoUrl.substring(1) : this.videoUrl, success: (res) => { console.log("文件存在,大小:", res.size); this.tryDifferentFormat(); }, fail: (err) => { console.error("文件不存在或无法访问:", err); this.tryAlternativeVideoPath(); } }); common_vendor.index.showToast({ title: "视频加载失败,请检查文件是否存在", icon: "none", duration: 2e3 }); }, // 添加新方法:尝试不同格式 tryDifferentFormat() { console.log("尝试不同的视频格式"); const formats = [ { ext: "mp4", mime: "video/mp4" }, { ext: "webm", mime: "video/webm" }, { ext: "ogg", mime: "video/ogg" }, { ext: "mov", mime: "video/quicktime" } ]; const currentPath = this.videoUrl; const basePath = currentPath.substring(0, currentPath.lastIndexOf(".")) || "/static/demo"; let nextFormat = formats.find((f) => !currentPath.endsWith(f.ext)); if (nextFormat) { this.videoUrl = `${basePath}.${nextFormat.ext}`; console.log("尝试新格式:", this.videoUrl); this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.stop(); videoContext.play(); } }); } else { this.useBuiltInResource(); } }, // 添加新方法:使用内置资源 useBuiltInResource() { console.log("尝试使用内置资源"); const platform = common_vendor.index.getSystemInfoSync().platform; if (platform === "windows") { process.env.UNI_INPUT_DIR || ""; this.videoUrl = `./static/demo.mp4`; console.log("Windows平台尝试路径:", this.videoUrl); } else if (platform === "android" || platform === "ios") { this.useNativeVideo(); } else { const baseUrl = window.location.origin; this.videoUrl = `${baseUrl}/static/demo.mp4`; console.log("Web平台尝试URL:", this.videoUrl); } this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, // 添加新方法:使用原生视频能力 useNativeVideo() { console.log("尝试使用原生视频能力"); common_vendor.index.chooseVideo({ sourceType: ["album"], success: (res) => { this.videoUrl = res.tempFilePath; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); }, fail: () => { this.videoPlaying = false; common_vendor.index.showToast({ title: "无法加载视频,显示静态图片", icon: "none" }); } }); }, // 处理视频结束事件 handleVideoEnded() { console.log("视频播放结束"); this.videoPlaying = false; this.showAnswerButton = true; }, // 处理答题按钮点击 handleAnswerButtonClick() { this.showAnswerButton = false; this.currentVideoIndex++; if (this.currentVideoIndex < this.videoList.length) { this.videoUrl = this.videoList[this.currentVideoIndex]; this.videoPlaying = true; this.currentSubtitle = ""; this.$nextTick(() => { const videoContext = common_vendor.index.createVideoContext("myVideo", this); if (videoContext) { videoContext.play(); } }); } else { common_vendor.index.showToast({ title: "面试完成", icon: "success", duration: 2e3 }); setTimeout(() => { common_vendor.index.navigateTo({ url: "/pages/interview-result/interview-result" }); }, 2e3); } }, // 处理相机错误 handleCameraError(e) { console.error("相机错误:", e); common_vendor.index.showToast({ title: "相机初始化失败,请检查权限设置", icon: "none" }); this.tryFallbackOptions(); }, // 添加新方法:尝试备用选项 tryFallbackOptions() { const systemInfo = common_vendor.index.getSystemInfoSync(); if (systemInfo.uniPlatform === "mp-weixin" || systemInfo.uniPlatform === "mp-alipay") { this.useMiniProgramCamera(); } else { this.showStaticCameraPlaceholder(); } }, // 添加新方法:使用小程序相机API useMiniProgramCamera() { console.log("尝试使用小程序相机组件"); this.useMiniProgramCameraComponent = true; }, // 添加新方法:显示静态图像 showStaticCameraPlaceholder() { console.log("显示静态摄像头占位图"); const img = document.createElement("img"); img.src = "/static/images/camera-placeholder.png"; img.className = "static-camera-image"; img.style.width = "100%"; img.style.height = "100%"; img.style.objectFit = "cover"; const container = this.$refs.userCameraVideo.parentNode; container.appendChild(img); }, // 处理视频时间更新事件 handleTimeUpdate(e) { const currentTime = e.target.currentTime; let currentSubtitles; if (this.currentVideoIndex === 0) { currentSubtitles = this.subtitles; } else if (this.currentVideoIndex === 1) { currentSubtitles = this.secondVideoSubtitles; } else if (this.currentVideoIndex === 2) { currentSubtitles = this.thirdVideoSubtitles; } else if (this.currentVideoIndex === 3) { currentSubtitles = this.fourthVideoSubtitles; } else if (this.currentVideoIndex === 4) { currentSubtitles = this.fifthVideoSubtitles; } else if (this.currentVideoIndex === 5) { currentSubtitles = this.sixthVideoSubtitles; } else { currentSubtitles = []; } const subtitle = currentSubtitles.find( (sub) => currentTime >= sub.startTime && currentTime < sub.endTime ); this.currentSubtitle = subtitle ? subtitle.text : ""; } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return common_vendor.e({ a: $data.videoUrl, b: common_vendor.o((...args) => $options.handleVideoError && $options.handleVideoError(...args)), c: common_vendor.o((...args) => $options.handleVideoEnded && $options.handleVideoEnded(...args)), d: common_vendor.o((...args) => $options.handleTimeUpdate && $options.handleTimeUpdate(...args)), e: $data.currentSubtitle }, $data.currentSubtitle ? { f: common_vendor.t($data.currentSubtitle) } : {}, { g: $data.showAnswerButton }, $data.showAnswerButton ? { h: common_vendor.o((...args) => $options.handleAnswerButtonClick && $options.handleAnswerButtonClick(...args)) } : {}, { i: $data.useMiniProgramCameraComponent }, $data.useMiniProgramCameraComponent ? { j: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args)) } : {}, { k: $data.loading }, $data.loading ? {} : {}, { l: $data.showDebugInfo }, $data.showDebugInfo ? common_vendor.e({ m: $data.assistantResponse }, $data.assistantResponse ? { n: common_vendor.t($data.assistantResponse) } : {}, { o: $data.audioTranscript }, $data.audioTranscript ? { p: common_vendor.t($data.audioTranscript) } : {}, { q: common_vendor.f($data.processedResponses, (item, index, i0) => { return common_vendor.e({ a: item.role }, item.role ? { b: common_vendor.t(item.role) } : {}, { c: item.transcript }, item.transcript ? { d: common_vendor.t(item.transcript) } : {}, { e: index }); }) }) : {}); } const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-464e78c6"]]); wx.createPage(MiniProgramPage);