戰(zhàn):基于AI與Remotion的自動(dòng)化演示視頻生成)
在項(xiàng)目開發(fā)中你是否遇到過(guò)這樣的困境精心打磨的產(chǎn)品或功能卻苦于沒(méi)有時(shí)間或技能制作一個(gè)吸引人的演示視頻向團(tuán)隊(duì)、客戶或投資人展示時(shí)靜態(tài)截圖和文字描述總顯得蒼白無(wú)力。DemoDay 這款 Claude 插件正是為了解決這一痛點(diǎn)而生。它利用 AI 的強(qiáng)大能力將你的項(xiàng)目描述、代碼片段或產(chǎn)品構(gòu)思自動(dòng)轉(zhuǎn)化為一段結(jié)構(gòu)清晰、畫面專業(yè)的演示視頻。本文將為你帶來(lái) DemoDay 插件的完整實(shí)戰(zhàn)指南從核心原理、環(huán)境配置到一步步創(chuàng)建你的第一個(gè) AI 生成演示視頻并深入探討其背后的 Remotion、Eleven Labs 等關(guān)鍵技術(shù)棧的集成與優(yōu)化。1. 背景與核心概念什么是 DemoDay在深入技術(shù)細(xì)節(jié)之前我們首先要理解 DemoDay 是什么以及它試圖解決什么問(wèn)題。1.1 DemoDay 的定義與價(jià)值DemoDay 是一個(gè)構(gòu)建在 Claude AI 平臺(tái)上的插件Plugin。它的核心功能是自動(dòng)化生成項(xiàng)目演示視頻。你不需要學(xué)習(xí)復(fù)雜的視頻剪輯軟件如 Premiere、Final Cut Pro也無(wú)需錄制屏幕和配音。只需向 Claude 提供關(guān)于你項(xiàng)目的自然語(yǔ)言描述、關(guān)鍵功能點(diǎn)甚至是代碼倉(cāng)庫(kù)的鏈接DemoDay 插件就能理解你的需求并調(diào)用一系列后端服務(wù)生成一個(gè)包含動(dòng)態(tài)界面演示、畫外音解說(shuō)、背景音樂(lè)和文字標(biāo)注的完整視頻。其核心價(jià)值在于提升展示效率將數(shù)小時(shí)甚至數(shù)天的視頻制作過(guò)程壓縮到幾分鐘的描述和生成等待時(shí)間。降低技術(shù)門檻開發(fā)者、產(chǎn)品經(jīng)理、創(chuàng)業(yè)者都可以輕松創(chuàng)建專業(yè)級(jí)的演示材料。標(biāo)準(zhǔn)化輸出確保每次演示的風(fēng)格、節(jié)奏和結(jié)構(gòu)都保持一致提升品牌專業(yè)度。快速迭代產(chǎn)品功能更新后可以迅速生成新的演示視頻保持宣傳材料同步。1.2 核心組件與技術(shù)棧拆解DemoDay 并非一個(gè)單一工具而是一個(gè)集成系統(tǒng)。理解其技術(shù)棧有助于我們后續(xù)的配置和問(wèn)題排查。Claude Claude Plugin API這是用戶交互的入口。Claude 作為“大腦”理解用戶的自然語(yǔ)言指令并協(xié)調(diào)調(diào)用 DemoDay 插件的功能。Plugin API 定義了插件與 Claude 交互的規(guī)范包括身份驗(yàn)證、能力聲明和請(qǐng)求處理。Remotion這是一個(gè)基于 React 和 Node.js 的編程式視頻創(chuàng)作庫(kù)。這是 DemoDay 的視頻渲染引擎。Remotion 允許開發(fā)者使用 React 組件和 TypeScript/JavaScript 來(lái)定義視頻的每一幀。DemoDay 利用 Remotion將項(xiàng)目描述轉(zhuǎn)化為具體的動(dòng)畫組件如代碼高亮、界面漸變、圖標(biāo)飛入等并最終渲染成 MP4 等視頻格式。Eleven Labs或類似 TTS 服務(wù)這是文本轉(zhuǎn)語(yǔ)音Text-to-Speech引擎負(fù)責(zé)生成視頻的旁白配音。Eleven Labs 以其自然、富有情感的語(yǔ)音合成而聞名。DemoDay 會(huì)將生成的視頻腳本發(fā)送給此類 API獲取高質(zhì)量的音頻文件并與視頻畫面同步。后端服務(wù)與編排一個(gè)負(fù)責(zé)協(xié)調(diào)工作的后端服務(wù)。它接收來(lái)自 Claude Plugin 的請(qǐng)求執(zhí)行以下流程解析項(xiàng)目描述生成視頻分鏡腳本和視覺(jué)元素描述。調(diào)用 Remotion 服務(wù)傳入?yún)?shù)以渲染視頻片段。調(diào)用 TTS API 生成配音音頻。將視頻片段、音頻、背景音樂(lè)進(jìn)行合成與混流。最終將生成好的視頻文件返回或上傳到指定存儲(chǔ)如 S3。1.3 與相關(guān)概念的區(qū)別Claude Code 與 Claude DesktopClaude Code 是專注于代碼編寫和理解的模式或早期實(shí)驗(yàn)項(xiàng)目Claude Desktop 是 Claude 的桌面應(yīng)用程序。而DemoDay 是一個(gè) Plugin它需要運(yùn)行在支持 Claude Plugin 的環(huán)境中如 Claude 官網(wǎng)或特定集成平臺(tái)為 Claude 增加了一項(xiàng)特定功能。API 中轉(zhuǎn)站/通用 API 調(diào)用DemoDay 內(nèi)部確實(shí)會(huì)調(diào)用多個(gè)第三方 API如 Eleven Labs但它提供了一個(gè)場(chǎng)景化的、端到端的解決方案。用戶無(wú)需關(guān)心每個(gè) API 的密鑰、請(qǐng)求格式和結(jié)果拼接只需關(guān)注項(xiàng)目本身。傳統(tǒng)錄屏軟件與 OBS、Camtasia 等工具不同DemoDay 生成的是合成視頻畫面元素是程序生成的圖形和動(dòng)畫而非真實(shí)的軟件界面。這使其更適合概念演示、架構(gòu)講解和早期產(chǎn)品預(yù)覽。2. 環(huán)境準(zhǔn)備與前置條件要使用或理解 DemoDay你需要準(zhǔn)備以下環(huán)境。請(qǐng)注意由于 DemoDay 可能是一個(gè)新興或特定平臺(tái)上的插件其公開的部署方式可能有限。本節(jié)將分為“作為使用者”和“作為開發(fā)者/探索者”兩個(gè)角度。2.1 作為使用者最低要求如果你想嘗試使用現(xiàn)成的 DemoDay 插件Claude 賬號(hào)與權(quán)限你需要一個(gè)能夠訪問(wèn) Claude 并安裝插件的賬號(hào)。請(qǐng)注意網(wǎng)絡(luò)上的提示“unfortunately, claude is not available to new users right now”表明新用戶注冊(cè)可能受限。網(wǎng)絡(luò)環(huán)境由于需要調(diào)用多個(gè)海外 API如 Eleven Labs穩(wěn)定的網(wǎng)絡(luò)連接是必須的。項(xiàng)目材料準(zhǔn)備好你想要制作視頻的項(xiàng)目描述。清晰的描述會(huì)得到更好的結(jié)果例如項(xiàng)目是做什么的一句話簡(jiǎn)介核心功能有哪些列出3-5點(diǎn)目標(biāo)用戶是誰(shuí)有無(wú)特定的顏色、Logo 或風(fēng)格要求可以提供代碼倉(cāng)庫(kù)鏈接或關(guān)鍵代碼片段。2.2 作為開發(fā)者/探索者深入技術(shù)棧如果你想了解其原理甚至搭建一個(gè)類似系統(tǒng)需要以下環(huán)境Node.js 環(huán)境Remotion 基于 Node.js。建議安裝 LTS 版本如 18.x, 20.x。# 檢查Node.js版本 node --version # 檢查npm版本 npm --versionPython 環(huán)境可選如果后端編排服務(wù)使用 Python例如 FastAPI、Flask則需要 Python 3.8。python --versionDocker可選但推薦用于容器化部署 Remotion 渲染服務(wù)、后端服務(wù)等保證環(huán)境一致性。API 密鑰Eleven Labs API Key需要在 Eleven Labs 官網(wǎng) 注冊(cè)并獲取。Claude API Key如果后端需要調(diào)用 Claude 進(jìn)行腳本生成需要在 Anthropic 控制臺(tái) 獲取。云存儲(chǔ)服務(wù)如 AWS S3用于存儲(chǔ)生成的視頻文件需要相應(yīng)的 Access Key 和 Secret Key。IDEVisual Studio Code 或 WebStorm用于開發(fā) Remotion 組件和后端代碼。3. 核心原理與工作流程拆解讓我們深入 DemoDay 的內(nèi)部看看從一句描述到一段視頻究竟經(jīng)歷了哪些步驟。3.1 端到端工作流程下圖展示了 DemoDay 處理一個(gè)請(qǐng)求的完整生命周期用戶輸入 | v Claude 界面 (集成 DemoDay Plugin) | -- (1) 用戶通過(guò)自然語(yǔ)言描述項(xiàng)目 v DemoDay Plugin 后端 | -- (2) 解析請(qǐng)求提取關(guān)鍵信息項(xiàng)目名、功能點(diǎn)、風(fēng)格 | -- (3) 調(diào)用 AI如 Claude API生成視頻腳本和分鏡描述 | -- (4) 根據(jù)分鏡描述動(dòng)態(tài)生成或組裝 Remotion React 組件 | -- (5) 調(diào)用 Remotion 渲染服務(wù)生成無(wú)聲視頻片段 | -- (6) 將視頻腳本發(fā)送至 Eleven Labs API生成配音音頻 | -- (7) 使用 FFmpeg 等工具將視頻、音頻、背景音樂(lè)合成 | -- (8) 將最終視頻上傳至云存儲(chǔ)如 S3生成可訪問(wèn)鏈接 v Claude 界面 | -- (9) 將視頻鏈接返回給用戶 v 用戶獲得演示視頻3.2 關(guān)鍵技術(shù)點(diǎn)詳解1. Claude Plugin 開發(fā)Claude Plugin 本質(zhì)上是一個(gè)遵循特定 OpenAPI 規(guī)范的 Web 服務(wù)。當(dāng)用戶在 Claude 中激活 DemoDay 插件并發(fā)送請(qǐng)求時(shí)Claude 會(huì)向該插件預(yù)定義的 API 端點(diǎn)發(fā)送一個(gè)結(jié)構(gòu)化的 HTTP POST 請(qǐng)求。一個(gè)簡(jiǎn)化的ai-plugin.json描述文件示例如下{ schema_version: v1, name_for_human: DemoDay, name_for_model: demoday, description_for_human: Create demo videos for your projects automatically., description_for_model: Plugin for generating professional demo videos from project descriptions..., auth: { type: service_http, authorization_type: bearer }, api: { type: openapi, url: https://your-demoday-backend.com/openapi.yaml }, logo_url: https://your-demoday-backend.com/logo.png, contact_email: supportexample.com, legal_info_url: https://example.com/legal }2. Remotion 視頻生成Remotion 的核心思想是“視頻即代碼”。一個(gè)最簡(jiǎn)單的 Remotion 組件如下// src/components/TitleScene.tsx import { AbsoluteFill, interpolate, useCurrentFrame } from remotion; export const TitleScene: React.FC{ title: string } ({ title }) { const frame useCurrentFrame(); // 獲取當(dāng)前幀數(shù) const opacity interpolate(frame, [0, 30], [0, 1]); // 在0到30幀間透明度從0漸變到1 return ( AbsoluteFill style{{ backgroundColor: white, justifyContent: center, alignItems: center }} h1 style{{ fontSize: 100, opacity }}{title}/h1 /AbsoluteFill ); };在 DemoDay 中后端服務(wù)會(huì)根據(jù)分鏡描述動(dòng)態(tài)生成類似這樣的組件代碼或從預(yù)定義的組件庫(kù)中組合然后傳遞給 Remotion 渲染。3. 音頻合成與處理Eleven Labs API 調(diào)用示例概念代碼// 后端服務(wù)中的音頻生成函數(shù) async function generateSpeech(text, voiceId 21m00Tcm4TlvDq8ikWAM) { const response await fetch(https://api.elevenlabs.io/v1/text-to-speech/${voiceId}, { method: POST, headers: { Accept: audio/mpeg, Content-Type: application/json, xi-api-key: process.env.ELEVEN_LABS_API_KEY // 從環(huán)境變量讀取密鑰 }, body: JSON.stringify({ text: text, model_id: eleven_monolingual_v1, voice_settings: { stability: 0.5, similarity_boost: 0.75 } }) }); if (!response.ok) { const errorText await response.text(); throw new Error(Eleven Labs TTS failed: ${response.status} ${errorText}); } const audioBuffer await response.arrayBuffer(); // 將 audioBuffer 保存為 MP3 文件 return audioBuffer; }重要提示API 密鑰必須妥善保管切勿提交到代碼倉(cāng)庫(kù)。應(yīng)使用環(huán)境變量或安全的密鑰管理服務(wù)。4. 完整實(shí)戰(zhàn)從零搭建一個(gè)簡(jiǎn)化版 DemoDay 后端由于完整的 DemoDay 系統(tǒng)涉及復(fù)雜的業(yè)務(wù)編排和多個(gè)服務(wù)我們將實(shí)現(xiàn)一個(gè)極度簡(jiǎn)化但可運(yùn)行的版本幫助你理解核心鏈路。這個(gè)版本將1) 接收項(xiàng)目描述2) 生成簡(jiǎn)單腳本3) 用 Remotion 渲染一個(gè)靜態(tài)標(biāo)題視頻4) 模擬音頻合成。4.1 項(xiàng)目初始化與結(jié)構(gòu)創(chuàng)建項(xiàng)目目錄并初始化。mkdir demoday-simplified-backend cd demoday-simplified-backend npm init -y安裝核心依賴npm install express cors dotenv npm install --save-dev typescript types/node types/express ts-node nodemon創(chuàng)建項(xiàng)目結(jié)構(gòu)demoday-simplified-backend/ ├── src/ │ ├── index.ts # Express 服務(wù)器入口 │ ├── remotion/ # Remotion 視頻渲染相關(guān) │ │ ├── index.ts # Remotion 渲染入口 │ │ └── MyVideo.tsx # 視頻組件 │ └── services/ │ └── scriptGenerator.ts # 簡(jiǎn)單的腳本生成邏輯 ├── .env # 環(huán)境變量文件需自行創(chuàng)建不提交git ├── .gitignore ├── package.json ├── tsconfig.json └── openapi.yaml # Claude Plugin 描述文件簡(jiǎn)化版4.2 配置 TypeScript 和 Express 服務(wù)器tsconfig.json:{ compilerOptions: { target: ES2020, module: commonjs, lib: [ES2020], outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true, forceConsistentCasingInFileNames: true, jsx: react-jsx }, include: [src/**/*], exclude: [node_modules] }src/index.ts- 基礎(chǔ)服務(wù)器import express from express; import cors from cors; import dotenv from dotenv; import { generateVideo } from ./remotion; dotenv.config(); const app express(); const port process.env.PORT || 3000; app.use(cors()); app.use(express.json()); // Claude Plugin 的健康檢查端點(diǎn)必需 app.get(/.well-known/ai-plugin.json, (req, res) { res.json({ schema_version: v1, name_for_human: DemoDay Simulator, name_for_model: demoday_simulator, description_for_human: A simplified demo video generator for projects., description_for_model: Generates a simple demo video based on project title and description., auth: { type: none }, // 簡(jiǎn)化版無(wú)認(rèn)證 api: { type: openapi, url: http://localhost:${port}/openapi.yaml }, logo_url: , contact_email: , legal_info_url: }); }); // 提供 OpenAPI 描述文件 app.get(/openapi.yaml, (req, res) { // 這里應(yīng)返回完整的 OpenAPI YAML為簡(jiǎn)化我們只定義一個(gè)端點(diǎn) res.setHeader(Content-Type, text/yaml); res.send( openapi: 3.0.1 info: title: DemoDay Simulator API description: Simulated API for generating demo videos. version: 1.0.0 servers: - url: http://localhost:${port} paths: /generate-demo: post: operationId: generateDemoVideo summary: Generate a simple demo video requestBody: required: true content: application/json: schema: type: object properties: project_title: type: string description: The title of the project. project_description: type: string description: A short description of the project. responses: 200: description: Video generation task started successfully. content: application/json: schema: type: object properties: message: type: string task_id: type: string estimated_time: type: number ); }); // 核心的視頻生成端點(diǎn) app.post(/generate-demo, async (req, res) { const { project_title, project_description } req.body; if (!project_title) { return res.status(400).json({ error: project_title is required }); } console.log(Received request for project: ${project_title}); try { // 1. 生成一個(gè)簡(jiǎn)單的視頻腳本模擬 const script This is a demo for: ${project_title}. ${project_description || An amazing project.}; // 2. 調(diào)用 Remotion 渲染視頻傳遞標(biāo)題和腳本 // 注意實(shí)際項(xiàng)目中這里應(yīng)該是異步任務(wù)隊(duì)列這里簡(jiǎn)化成同步 const videoFilePath await generateVideo(project_title, script); // 3. 模擬上傳到云存儲(chǔ)并返回鏈接 const videoUrl https://your-storage-bucket.s3.amazonaws.com/generated/${Date.now()}_${project_title.replace(/\s/g, _)}.mp4; res.json({ message: Video generation started successfully., task_id: task_${Date.now()}, estimated_time: 30, // 模擬預(yù)計(jì)時(shí)間 video_url: videoUrl, // 模擬的最終視頻地址 script: script // 返回生成的腳本供調(diào)試 }); } catch (error) { console.error(Video generation failed:, error); res.status(500).json({ error: Internal server error during video generation. }); } }); app.listen(port, () { console.log(DemoDay Simulator backend listening on port ${port}); });4.3 實(shí)現(xiàn)簡(jiǎn)化的 Remotion 視頻渲染首先在項(xiàng)目?jī)?nèi)初始化 Remotion 并安裝依賴npx create-videolatest --template hello-world remotion-video # 將生成的 remotion-video 目錄內(nèi)容移動(dòng)到 src/remotion/ 下或直接在該目錄開發(fā) # 這里為了簡(jiǎn)化我們手動(dòng)創(chuàng)建核心文件。安裝 Remotion 核心包npm install remotion remotion/cli創(chuàng)建src/remotion/MyVideo.tsximport { Composition, AbsoluteFill, useCurrentFrame, interpolate, spring } from remotion; import { loadFont } from remotion/google-fonts/Inter; const { fontFamily } loadFont(); // 定義組件的 Props type MyVideoProps { title: string; script: string; }; // 主場(chǎng)景組件 const MyVideoComponent: React.FCMyVideoProps ({ title, script }) { const frame useCurrentFrame(); const opacity interpolate(frame, [0, 30], [0, 1], { extrapolateRight: clamp }); // 標(biāo)題彈入動(dòng)畫 const titleScale spring({ frame, fps: 30, from: 0.8, to: 1, durationInFrames: 45, }); return ( AbsoluteFill style{{ backgroundColor: #0F172A, fontFamily, color: white }} {/* 標(biāo)題 */} div style{{ position: absolute, top: 20%, width: 100%, textAlign: center, transform: scale(${titleScale}), opacity, }} h1 style{{ fontSize: 80, marginBottom: 20 }}{title}/h1 p style{{ fontSize: 40, color: #94A3B8 }}Project Demo/p /div {/* 腳本內(nèi)容從底部滑入 */} div style{{ position: absolute, bottom: 15%, width: 80%, left: 10%, textAlign: center, opacity: interpolate(frame, [60, 90], [0, 1]), transform: translateY(${interpolate(frame, [60, 90], [50, 0])}px) }} p style{{ fontSize: 32, lineHeight: 1.5 }}{script}/p /div {/* 底部裝飾 */} div style{{ position: absolute, bottom: 0, width: 100%, height: 60, backgroundColor: #1E293B, display: flex, justifyContent: center, alignItems: center, opacity: interpolate(frame, [90, 120], [0, 1]) }} span style{{ fontSize: 24 }}Generated with ?? by DemoDay/span /div /AbsoluteFill ); }; // Remotion 組合Composition定義 export const RemotionDemo: React.FC () { return ( Composition idMyDemoVideo component{MyVideoComponent} durationInFrames{150} // 5秒30fps fps{30} width{1920} height{1080} defaultProps{{ title: Default Project, script: This is a default project description., }} / / ); };創(chuàng)建src/remotion/index.ts- 渲染入口import { bundle } from remotion/bundler; import { renderMedia, selectComposition } from remotion/renderer; import { webpackOverride } from ../webpack-override; // 如果需要自定義webpack配置 import path from path; import fs from fs/promises; // 簡(jiǎn)化版實(shí)際需要更復(fù)雜的臨時(shí)文件管理和配置 export async function generateVideo(title: string, script: string): Promisestring { console.log(Starting Remotion bundle...); // 1. 創(chuàng)建臨時(shí)入口文件動(dòng)態(tài)傳遞 props const tempEntryPath path.join(__dirname, _temp_entry_${Date.now()}.tsx); const entryContent import { registerRoot } from remotion; import { RemotionDemo } from ./MyVideo; registerRoot(RemotionDemo); ; await fs.writeFile(tempEntryPath, entryContent); // 2. 打包在實(shí)際項(xiàng)目中可以預(yù)打包這里簡(jiǎn)化流程 // const bundleLocation await bundle(tempEntryPath, webpackOverride); // 3. 選擇組合并渲染 // 為了簡(jiǎn)化示例我們跳過(guò)實(shí)際的渲染模擬一個(gè)過(guò)程 console.log([Simulation] Rendering video for: ${title}); console.log([Simulation] Script: ${script}); // 模擬渲染耗時(shí) await new Promise(resolve setTimeout(resolve, 2000)); // 4. 清理臨時(shí)文件 await fs.unlink(tempEntryPath).catch(() {}); // 返回模擬的文件路徑 const outputPath path.join(__dirname, ../../tmp/output_${Date.now()}.mp4); console.log([Simulation] Video would be saved to: ${outputPath}); return outputPath; }4.4 運(yùn)行與測(cè)試啟動(dòng)后端服務(wù)器 在package.json中添加腳本scripts: { dev: nodemon --exec ts-node src/index.ts, build: tsc }運(yùn)行npm run dev服務(wù)器將在http://localhost:3000啟動(dòng)。測(cè)試 API 端點(diǎn) 使用curl或 Postman 測(cè)試curl -X POST http://localhost:3000/generate-demo \ -H Content-Type: application/json \ -d { project_title: AI Code Reviewer, project_description: An automated tool that reviews pull requests using large language models. }預(yù)期返回{ message: Video generation started successfully., task_id: task_1645678901234, estimated_time: 30, video_url: https://your-storage-bucket.s3.amazonaws.com/generated/1645678901234_AI_Code_Reviewer.mp4, script: This is a demo for: AI Code Reviewer. An automated tool that reviews pull requests using large language models. }高級(jí)集成 Claude Plugin 要將此服務(wù)作為 Claude Plugin 運(yùn)行你需要將服務(wù)部署到公網(wǎng)如 Vercel, Railway, 或自有服務(wù)器。配置正確的ai-plugin.json和openapi.yaml中的 URL。在 Claude 的插件開發(fā)設(shè)置中輸入你的插件 manifest URLhttps://your-deployed-service.com/.well-known/ai-plugin.json。由于認(rèn)證和 CORS 限制這需要更復(fù)雜的配置超出了簡(jiǎn)化版的范圍。5. 常見問(wèn)題與排查思路在實(shí)際使用或開發(fā)類似 DemoDay 的系統(tǒng)時(shí)你會(huì)# 1. 兩數(shù)之和題目給定一個(gè)整數(shù)數(shù)組 nums 和一個(gè)整數(shù)目標(biāo)值 target請(qǐng)你在該數(shù)組中找出 和為目標(biāo)值 target 的那 兩個(gè) 整數(shù)并返回它們的數(shù)組下標(biāo)。你可以假設(shè)每種輸入只會(huì)對(duì)應(yīng)一個(gè)答案。但是數(shù)組中同一個(gè)元素在答案里不能重復(fù)出現(xiàn)。你可以按任意順序返回答案。思路使用哈希表 將數(shù)組中的元素作為key 數(shù)組下標(biāo)作為value遍歷數(shù)組 如果target - nums[i] 在哈希表中存在 那么返回兩個(gè)下標(biāo)如果不存在 將當(dāng)前元素和下標(biāo)存入哈希表代碼class Solution { public: vectorint twoSum(vectorint nums, int target) { unordered_mapint,int map; for(int i 0; i nums.size(); i) { auto iter map.find(target - nums[i]); if(iter ! map.end()) { // 找到了 return {iter-second,i}; } // 沒(méi)有找到 將當(dāng)前元素插入哈希表 map.insert(pairint,int(nums[i],i)); } return {}; } };