自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用 Gemini API 構(gòu)建視頻字幕生成器

譯文 精選
人工智能
在本教程中,你將使用 Google 的 Gemini API 構(gòu)建人工智能驅(qū)動的字幕生成器。我們將創(chuàng)建一個名為“AI-Subtitle-Generator”的項目,該項目的前端使用 React,后端使用 Express。準(zhǔn)備好了嗎?讓我們馬上出發(fā)吧!

譯者 | 崔皓

審校 | 重樓

開篇

在本教程中,將使用 Google 的 Gemini API 構(gòu)建人工智能驅(qū)動的字幕生成器。我們將創(chuàng)建一個名為“AI-Subtitle-Generator”的項目,該項目的前端使用 React,后端使用 Express。準(zhǔn)備好了嗎?讓我們馬上出發(fā)吧!

先決條件

構(gòu)建項目之前你需要對React 和 Express 有基本了解。

Gemini API 是什么?

Google 的 Gemini API 是一款功能強大的工具,可讓將高級 AI 功能集成到的應(yīng)用程序中。 Gemini 是多模態(tài)模型,它支持用戶使用各種類型的輸入,例如文本、圖像、音頻和視頻。

它擅長分析和處理大量文本,特別是從視頻中提取信息的能力,非常適合字幕生成器的項目。

如何獲取 API 密鑰

API 密鑰充當(dāng)唯一標(biāo)識符并驗證對服務(wù)的請求。它對于訪問和使用 Gemini AI 的功能至關(guān)重要。這個密鑰將允許我們的應(yīng)用程序與 Gemini 進(jìn)行通信,也是構(gòu)建該項目的關(guān)鍵因素。

如下圖所示,進(jìn)入Google AI Studio ,然后點擊“獲取 API 密鑰”(Get API key)

在打開的API KEY 頁面,單擊“創(chuàng)建 API 密鑰”:

該操作將創(chuàng)建一個新的 API 密鑰,并復(fù)制密鑰對其進(jìn)行妥善保存

這個就是訪問Gemini API 密鑰。此密鑰用于驗證應(yīng)用程序?qū)?Gemini API 的請求。每次應(yīng)用程序向 Gemini 發(fā)送請求時,都必須包含此密鑰。 Gemini 使用此密鑰來驗證請求是否來自授權(quán)來源。如果沒有此 API 密鑰,請求將被拒絕,同時應(yīng)用也無法訪問 Gemini 的服務(wù)。

項目設(shè)置

首先,基于項目創(chuàng)建一個新文件夾。我們稱之為ai-subtitle-generator 。

在ai-subtitle-generator文件夾內(nèi),創(chuàng)建兩個子文件夾: client和server 。 client文件夾將包含 React 前端, server文件夾將包含 Express 后端。

前端設(shè)置

我們先將重點關(guān)注放到前端,并設(shè)置一個基本的 React 應(yīng)用程序。

通過如下命令,導(dǎo)航到client文件夾:

cd client

使用Vite創(chuàng)建一個新的React項目。執(zhí)行如下命令:

npm create vite@latest .

根據(jù)提示時,選擇“React、“React + TS”或者“React + JS”。在本教程中,將使用 React + TS。當(dāng)然你也可以根據(jù)喜好選擇其他的選項。

接下來,使用以下命令安裝依賴項:

npm install

然后啟動開發(fā)服務(wù)器:

npm run dev

在前端處理文件上傳

現(xiàn)在在client/src/App.tsx中,添加以下代碼:

//  client/src/App.tsx
const App = () => {
    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>): Promise<void> => {
    e.preventDefault();
    try {
      const formData = new FormData(e.currentTarget);
      console.log(formData)
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="file" accept="video/*,.mkv" name="video" />
        <input type="submit" />
      </form>
    </div>
  );
};
export default App;

在上面的代碼中,我們使用了一個輸入標(biāo)簽來接受視頻并將其命名為video 。該名稱將附加到FormData對象中。

在將視頻發(fā)送到服務(wù)器的過程中,使用到了“鍵值對“的發(fā)送方式,其中是video ,值是文件數(shù)據(jù)。

為什么是鍵值對?因為當(dāng)服務(wù)器收到請求時,它需要解析傳入的塊。解析后,視頻數(shù)據(jù)將在req.files[key]中使用,其中key是前端分配的名稱(在本例中為video )。

這就是為什么使用FormData對象的原因。當(dāng)創(chuàng)建一個新的FormData實例并將e.target傳遞給它時,所有表單字段及其名稱將自動生成鍵值對的形式。

服務(wù)器設(shè)置

目前為止,我們已經(jīng)獲取了API 密鑰,接著需要設(shè)置后端服務(wù)器。該服務(wù)器將處理來自前端上傳視頻,并與 Gemini API 進(jìn)行通信從而生成字幕。

通過如下命令,導(dǎo)航到server文件夾:

cd server

并初始化項目:

npm init -y

然后安裝必要的包:

npm install express dotenv cors @google/generative-ai express-fileupload nodemon

這些是在此項目中使用的后端依賴項:

  • express 用于創(chuàng)建后端 API 的 Web 框架。
  • dotenv 從.env文件加載環(huán)境變量。
  • cors 啟用跨源資源共享,允許前端與后端進(jìn)行通信。
  • @google/generative-ai 用于與 Gemini API 交互的 Google AI 庫。
  • express-fileupload 處理文件上傳,可以輕松訪問服務(wù)器上上傳的文件。
  • nodemon 更改代碼時自動重新啟動服務(wù)器。

設(shè)置環(huán)境變量

現(xiàn)在,創(chuàng)建一個名為.env的文件??梢栽诖颂幑芾?API 密鑰。

//.env
API_KEY = YOUR_API_API
PORT = 3000

更新package.json

對于項目,我們使用 ES6 模塊而不是 CommonJS。要啟用此功能,請使用以下代碼更新的package.json文件:

{
  "name": "server",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",       //Add "type": "module" to enable ES6 modules
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"    //configure nodemon
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "@google/generative-ai": "^0.21.0",
    "cors": "^2.8.5",
    "dotenv": "^16.4.7",
    "express": "^4.21.1",
    "express-fileupload": "^1.5.1",
    "nodemon": "^3.1.7"
  }
}

Express 的基本設(shè)置

創(chuàng)建文件server.js 。現(xiàn)在,讓我們設(shè)置一個基本的 Express 應(yīng)用程序。

//  server/server.js

import express from "express";
import { configDotenv } from "dotenv";
import fileUpload from "express-fileupload";
import cors from "cors"

const app = express();

configDotenv();           //configure the env
app.use(fileUpload());    //it will parse the mutipart data
app.use(express.json());  // Enable JSON parsing for request bodies
app.use(cors())           //configure cors

app.use("/api/subs",subRoutes);  // Use routes for the "/api/subs" endpoint

app.listen(process.env.PORT, () => {   //access the PORT from the .env
  console.log("server started");         
});

在代碼中,我們創(chuàng)建一個 Express 應(yīng)用程序?qū)嵗?,然后加載環(huán)境變量。該環(huán)境變量可以用來保存API 密鑰等敏感數(shù)據(jù)。接下來,利用中間件: fileUpload準(zhǔn)備服務(wù)器來接收上傳的視頻, express.json允許接收 JSON 數(shù)據(jù), cors允許前端和后端之間的通信。

接著,定義路由(/api/subs)來處理與字幕生成相關(guān)的所有請求。路由的具體邏輯將在subs.routes.js中體現(xiàn)。最后,啟動服務(wù)器,告訴它監(jiān)聽.env文件中定義的端口,從而保證請求響應(yīng)。

然后,創(chuàng)建一系列文件夾來管理代碼。當(dāng)然,也可以在單個文件中管理代碼,但將其構(gòu)建到單獨的文件夾進(jìn)行管理更加方便、更加清晰

下面是服務(wù)器的最終文件夾結(jié)構(gòu):

server/

├── server.js

├── controller/

│ └── subs.controller.js

├── gemini/

│ ├── gemini.config.js

├── routes/

│ └── subs.routes.js

├── uploads/

├── utils/

│ ├── fileUpload.js

│ └── genContent.js

└── .env

注意:現(xiàn)在不必?fù)?dān)心創(chuàng)建此文件夾結(jié)構(gòu)。這僅供參考。跟著文章一步步來,在后面的內(nèi)容中會逐步搭建這個結(jié)構(gòu)。

創(chuàng)建路由

創(chuàng)建一個routes文件夾,然后創(chuàng)建subs.routes.js文件如下

// server/routes/sub.routes.js
import express from "express"
import { uploadFile } from "../controller/subs.controller.js"    // import the uploadFile function from the controller folder

const router = express.Router()

router.post("/",uploadFile)    // define a POST route that calls the uploadFile function

export default router     // export the router to use in the main server.js file

此代碼定義了服務(wù)器的路由,特別是處理視頻上傳和字幕生成的路由。

使用express.Router()創(chuàng)建一個新的路由器實例。這使我們能夠定義新的路由,該路由可以獨立于主服務(wù)器路由,從而改進(jìn)代碼組織結(jié)構(gòu),使之更加清晰。在 API 接入點的根路徑("/")處定義 POST 路由。當(dāng)對此路由發(fā)出 POST 請求時(當(dāng)用戶在前端提交視頻上傳表單時會發(fā)生),將調(diào)用uploadFile函數(shù)。該函數(shù)將處理實際的上傳和字幕生成。

最后,我們導(dǎo)出路由器,以便可以在主服務(wù)器文件(server.js)中使用它來將此路由連接到主應(yīng)用程序。

配置Gemini

接下來的任務(wù)就是配置應(yīng)用程序如何與 Gemini 交互。

創(chuàng)建一個gemini文件夾,然后創(chuàng)建一個名為gemini.config.js的新文件:

//  server/gemini/gemini.config.js

import {
  GoogleGenerativeAI,
  HarmBlockThreshold,
  HarmCategory,
} from "@google/generative-ai";
import { configDotenv } from "dotenv";
configDotenv();

const genAI = new GoogleGenerativeAI(process.env.API_KEY);  // Initialize Google Generative AI with the API key

const safetySettings = [
  {
    category: HarmCategory.HARM_CATEGORY_HARASSMENT,
    threshold: HarmBlockThreshold.BLOCK_NONE,
  },
  {
    category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
    threshold: HarmBlockThreshold.BLOCK_NONE,
  },
  {
    category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
    threshold: HarmBlockThreshold.BLOCK_NONE,
  },
  {
    category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
    threshold: HarmBlockThreshold.BLOCK_NONE,
  },
];

const model = genAI.getGenerativeModel({
  model: "gemini-1.5-flash-001",    //choose the model
  safetySettings: safetySettings,   //optional safety settings
});
export default model;    //export the model

在上面的代碼中, safetySettings是可選的。這些設(shè)置允許定義 Gemini 輸出中潛在有害內(nèi)容(例如仇恨言論、暴力或露骨內(nèi)容)的閾值。

創(chuàng)建一個控制器來處理端點邏輯

創(chuàng)建一個controller文件夾,并在其中創(chuàng)建一個名為subs.controller.js的文件。在此文件中,將處理與 Gemini 模型交互的端點邏輯。

在 server/controller/subs.controller.js ,添加這段代碼:

// server/controller/subs.controller.js

import { fileURLToPath } from "url";
import path from "path";
import fs from "fs";

const __filename = fileURLToPath(import.meta.url);  //converts the module URL to a file path
const __dirname = path.dirname(__filename);   //get the current file directory

export const uploadFile = async (req, res) => {
  try {
    if (!req.files || !req.files.video) {   //if there is no file available, return error to the client
      return res.status(400).json({ error: "No video uploaded" });
    }

    const videoFile = req.files.video;   //access the video
    const uploadDir = path.join(__dirname, "..", "uploads");   //path to upload the video temporarily

    if (!fs.existsSync(uploadDir)) {   //check if the directory exists
      fs.mkdirSync(uploadDir);      //if not create a new one
    }

    const uploadPath = path.join(uploadDir, videoFile.name);  

    await videoFile.mv(uploadPath);  //it moves the video from the buffer to the "upload" folder

    return res.status(200).json({ message:"file uploaded sucessfully" });
  } catch (error) {
    return res
      .status(500)
      .json({ error: "Internal server error: " + error.message });
  }
};

由于我們使用的是 ES6 模塊,因此__dirname默認(rèn)情況下不可用。與 CommonJS 相比,文件處理機制有所不同。因此,將使用fileURLToPath來處理文件路徑。

將文件從默認(rèn)的臨時位置(緩沖區(qū))移動到uploads夾。

但文件上傳過程尚未完成。我們?nèi)匀恍枰獙⑽募l(fā)送到Google AI文件管理器,上傳后,它會返回一個URI,模型會使用這個URI進(jìn)行視頻分析。

如何將文件上傳到 Google AI 文件管理器

創(chuàng)建文件夾utils并創(chuàng)建文件fileUpload.js 。可以參考上面提供的文件夾結(jié)構(gòu)。

//  server/utils/fileUpload.js

import { GoogleAIFileManager, FileState } from "@google/generative-ai/server";
import { configDotenv } from "dotenv";
configDotenv();

export const fileManager = new GoogleAIFileManager(process.env.API_KEY);  //create a new GoogleAIFileManager instance

export async function fileUpload(path, videoData) {  
  try {
    const uploadResponse = await fileManager.uploadFile(path, {   //give the path as an argument
      mimeType: videoData.mimetype,  
      displayName: videoData.name,
    });
    const name = uploadResponse.file.name;
    let file = await fileManager.getFile(name);    
    while (file.state === FileState.PROCESSING) {     //check the state of the file
      process.stdout.write(".");
      await new Promise((res) => setTimeout(res, 10000));   //check every 10 second
      file = await fileManager.getFile(name);
    }
    if (file.state === FileState.FAILED) {   
      throw new Error("Video processing failed");
    }
    return file;   // return the file object, containing the upload file information and the uri
  } catch (error) {
    throw error;
  }
}

在上面的代碼中,我們創(chuàng)建了一個名為fileUpload的函數(shù),它帶有兩個參數(shù)。這些參數(shù)將從控制器函數(shù)傳遞,我們稍后將對其進(jìn)行設(shè)置。

fileUpload函數(shù)使用fileManager.uploadFile方法將視頻發(fā)送到 Google 的服務(wù)器。此方法需要兩個參數(shù):文件路徑和包含文件元數(shù)據(jù)(其 MIME 類型和顯示名稱)的對象。

由于 Google 服務(wù)器上的視頻處理需要時間,因此我們需要檢查文件的狀態(tài)。我們使用一個循環(huán)來執(zhí)行此操作,該循環(huán)使用fileManager.getFile()每 10 秒檢查一次文件的狀態(tài)。只要文件的狀態(tài)為PROCESSING,循環(huán)就會繼續(xù)。一旦狀態(tài)更改為SUCCESS或FAILED ,循環(huán)就會停止。

然后,該函數(shù)檢查處理是否成功。如果是,則返回文件對象,其中包含有關(guān)上傳和處理的視頻的信息,包括其 URI。否則,如果狀態(tài)為FAILED ,該函數(shù)將引發(fā)錯誤。

將 URI 傳遞給 Gemini 模型

在utils文件夾中,創(chuàng)建一個名為genContent.js的文件:

// server/utils/genContent.js

import model from "../gemini/gemini.config.js";
import { configDotenv } from "dotenv";
configDotenv();

export async function getContent(file) {
  try {
    const result = await model.generateContent([
      {
        fileData: {
          mimeType: file.mimeType,
          fileUri: file.uri,
        },
      },
      {
        text: "You need to write a subtitle for this full video, write the subtitle in the SRT format, don't write anything else other than a subtitle in the response, create accurate subtitle.",
      },
    ]);
    return result.response.text();
  } catch (error) {
    throw error;
  }
}

導(dǎo)入我們之前配置的模型。創(chuàng)建一個名為getContent的函數(shù)。 getContent函數(shù)獲取文件對象(從fileUpload函數(shù)返回)。

將文件 URI 和mimi傳遞給模型。然后,我們將提供提示,指示模型為整個視頻生成 SRT 格式的字幕。如果需要,還可以添加提示。然后返回響應(yīng)。

更新subs.controller.js文件

最后,我們需要更新控制器文件。我們已經(jīng)創(chuàng)建了fileUpload和getContent函數(shù),現(xiàn)在我們將在控制器中使用它們并提供所需的參數(shù)。

在 server/controller/subs.controller.js :

//  server/controller/subs.controller.js

import { fileURLToPath } from "url";
import path from "path";
import fs from "fs";
import { fileUpload } from "../utils/fileUpload.js";
import { getContent } from "../utils/genContent.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export const uploadFile = async (req, res) => {
  try {
    if (!req.files || !req.files.video) {
      return res.status(400).json({ error: "No video uploaded" });
    }

    const videoFile = req.files.video;
    const uploadDir = path.join(__dirname, "..", "uploads");

    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir);
    }

    const uploadPath = path.join(uploadDir, videoFile.name);

    await videoFile.mv(uploadPath);

    const response = await fileUpload(uploadPath, req.files.video);  //we pass 'uploadPath' and the video file data to 'fileUpload'
    const genContent = await getContent(response);   //the 'response' (containing the file URI) is passed to 'getContent'

    return res.status(200).json({ subs: genContent });   //// return the generated subtitles to the client
  } catch (error) {
    console.error("Error uploading video:", error);
    return res
      .status(500)
      .json({ error: "Internal server error: " + error.message });
  }
};

至此,后臺API就完成了。現(xiàn)在,我們將繼續(xù)更新前端。

更新前端

我們的前端目前只允許用戶選擇視頻。在本節(jié)中,我們將更新它以將視頻數(shù)據(jù)發(fā)送到后端進(jìn)行處理。然后,前端將從后端接收生成的字幕并啟動.srt文件的下載。

導(dǎo)航到client文件夾:

cd client

安裝axios 。我們將使用它來處理 HTTP 請求。

npm install axios

client/src/App.tsx

//   client/src/App.tsx

import axios from "axios";

const App = () => {
  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>): Promise<void> => {
    e.preventDefault();
    try {
      const formData = new FormData(e.currentTarget);
      // sending a POST request with form data
      const response = await axios.post(
        "http://localhost:3000/api/subs/",   
        formData
      );
// creating a Blob from the server response and triggering the file download
      const blob = new Blob([response.data.subs], { type: "text/plain" }); 
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = "subtitle.srt";
      link.click();
      link.remove();
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="file" accept="video/*,.mkv" name="video" />
        <input type="submit" />
      </form>
    </div>
  );
};
export default App;

axios向后端 API 端點(/api/subs)發(fā)出 POST 請求。服務(wù)器將處理視頻,這可能需要一些時間。

服務(wù)器發(fā)送生成的字幕后,前端接收它們作為響應(yīng)。為了處理此響應(yīng)并允許用戶下載字幕,我們將使用 Blob。 Blob(二進(jìn)制大對象)是一種 Web API 對象,表示原始二進(jìn)制數(shù)據(jù),本質(zhì)上就像文件一樣。在我們的例子中,從服務(wù)器返回的字幕將被轉(zhuǎn)換為 Blob,然后可以在用戶的瀏覽器中觸發(fā)下載。

概括

在本教程中,學(xué)習(xí)了如何使用 Google 的 Gemini API、React 和 Express 構(gòu)建人工智能驅(qū)動的字幕生成器。可以上傳視頻,發(fā)送到Gemini API進(jìn)行字幕生成,并提供生成的字幕供下載。

結(jié)論

就是這樣!已使用 Gemini API 成功構(gòu)建了人工智能驅(qū)動的字幕生成器。為了更快地進(jìn)行測試,請從較短的視頻剪輯(3-5 分鐘)開始。較長的視頻可能需要更多時間來處理。

想要創(chuàng)建可定制的視頻提示應(yīng)用程序嗎?只需添加一個輸入字段,讓用戶輸入提示,將該提示發(fā)送到服務(wù)器,并使用它代替硬編碼的提示。僅此而已。

譯者介紹

崔皓,51CTO社區(qū)編輯,資深架構(gòu)師,擁有18年的軟件開發(fā)和架構(gòu)經(jīng)驗,10年分布式架構(gòu)經(jīng)驗。


責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2022-12-15 08:49:58

ReactQR生成器

2022-11-21 17:44:03

機器學(xué)習(xí)文本生成器自然語言

2022-10-17 18:29:55

2022-08-28 19:10:37

JavaScript二維碼源碼

2024-02-23 15:53:13

OpenAISora人工智能

2021-12-10 09:45:19

生成器配置代碼

2010-09-07 16:31:17

SQL語句insert

2021-04-22 21:15:38

Generator函數(shù)生成器

2011-12-23 13:42:05

JavaScript

2021-11-04 09:00:00

JavaSpring BootURL

2015-08-25 11:07:58

2017-07-01 16:02:39

分布式ID生成器

2025-01-23 08:36:27

CSS開發(fā)工具

2024-11-01 15:51:06

2024-02-18 08:00:00

PythonAI多模態(tài)模型API

2022-02-22 08:20:04

React工具PDF 文件

2023-05-17 16:02:00

CSS工具代碼生成器

2023-07-02 14:14:37

ChatGPTMidjourney

2021-07-23 11:24:54

Create Inc開源G代碼生成器

2015-08-25 15:54:17

程序員代碼生成器
點贊
收藏

51CTO技術(shù)棧公眾號