前端实现视频url转文章

35 阅读1分钟

www.youtube.com/watch?v=BIp…

开发者工具技巧

示例:

chat.openai.com/share/ff2a5…

chat.openai.com/share/b5268…

最好能在输出技巧时,提供youtube链接对应的时间点(由字幕提供)直接打开到相应位置

实现思路

获取单个链接或同系列链接

获取多个链接使用库 youtube-sr

const urlList = await YouTube.getPlaylist(listID, {fetchAll: true});

也可以用来搜索获取链接

const urlList = await YouTube.search(search as string, {
    limit: 5,
    type: "video",
  });

获取视频字幕

使用库youtube-captions-scraper

// types/youtube-captions-scraper.d.ts
declare module 'youtube-captions-scraper' {
    export function getSubtitles(options: {
        videoID: string;
        lang?: string;
    }): Promise<CaptionsType>;
}
let result: CaptionsItem[] = await getSubtitles({
      videoID,
      lang: "en", // 你可以指定你想要的语言
    });

优化一段prompt 命令输出文章小结及拼接时间跳转链接

const getPromptText = (data: getPromptTextParams) => `
  #第一、markdown形式,返回中文
  #第二、${data.prompt || DEFAULT_PROMPT}
  ${
    data.appendTime &&
    `#第三,列出要点并附上视频时间跳转链接,[time](${data.videoUrl}&t=[time]s)#例如:[3.319](${data.videoUrl}&t=3.319s),[6.96](${data.videoUrl}&t=6.96s)。`
  }
  以下是提供的字幕文段:\n
  ${data.captains}
`;

请求gpt接口

需要配置APIKEY和BASEURL

const openai = new OpenAI({
  apiKey: APIKEY,
  baseURL: BASEURL,
});

配置流式请求头

/ 设置必要的 HTTP 头
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");
  res.flushHeaders();

发起流式请求

try {
    // 发起请求到 OpenAI 的接口
    const response = await openai.chat.completions.create({
      temperature: 0.01,
      model: "gpt-3.5-turbo",
      messages: [
        { role: "system", content: roleDuty },
        { role: "user", content: JSON.stringify({ prompt: promptText }) },
      ],
      stream: true,
    });
    // 将数据流式地发送到客户端
    for await (const chunk of response) {
      let message = chunk.choices[0]?.delta?.content || "";
      res.write(`data: ${JSON.stringify(message)}\n\n`);
    }
    res.end();
  }

接收流式请求

const asyncEvent2 = async () => {
    const ctrl2 = new AbortController();
    fetchEventSource(`/api/urlToEssay_v2?videoUrl=${url}`, {
      method: "POST",
      body: JSON.stringify({
        prompt,
      }),
      signal: ctrl2.signal,
      onmessage: (event) => {
        essayRef.current += JSON.parse(event.data);
      },
      onerror: (event) => {
        // console.log("asyncEvent2", event);
        throw event;
      },
      onclose: () => {
        setEssay(essayRef.current);
        essayRef.current=''
        ctrl2.abort()
      },
    });
  };

也可以以非流式请求调用的方式,只是接口等待时间有点久。