AI 视频理解:让 Agent 看视频并总结内容

B 站技术区的视频,动辄 40 分钟起。我有个习惯------每看到一个"标记稍后看"的视频,它基本就永远躺在列表里了。

上个月我写了一个工具:把视频丢进去,10 分钟后给你一份 300 字的摘要,包含核心观点和时间轴。不是看标题和字幕瞎猜------是真的提取画面,让 AI 看画面内容。

这篇文章把完整实现给你。核心技术:ffmpeg 提取关键帧 → Vision API 理解每一帧 → LLM 串联成摘要。


整体思路

视频太长,AI 不可能一帧帧看。核心策略是采样

复制代码
视频文件(.mp4)
  → ffmpeg 每 30 秒抽一帧(关键帧变化大的地方多抽)
    → 每帧交给 Vision API 描述画面内容
      → 把所有帧的描述拼起来
        → LLM 生成主题摘要 + 时间轴

这跟 10 万行日志分析(场景四)的思路一模一样------采样,不是全量。


第一步:ffmpeg 提取关键帧

go 复制代码
package main

import (
    "fmt"
    "os"
    "os/exec"
    "path/filepath"
    "strconv"
    "strings"
)

// 从视频中按时间间隔抽取关键帧
func extractFrames(videoPath, outputDir string, intervalSec int) ([]string, error) {
    os.MkdirAll(outputDir, 0755)

    // ffmpeg 每 N 秒抽一帧,保存为 jpg
    outputPattern := filepath.Join(outputDir, "frame-%04d.jpg")
    cmd := exec.Command("ffmpeg",
        "-i", videoPath,
        "-vf", fmt.Sprintf("fps=1/%d", intervalSec), // 每 intervalSec 秒一帧
        "-q:v", "3",              // 高质量
        "-y",
        outputPattern,
    )
    if err := cmd.Run(); err != nil {
        return nil, fmt.Errorf("ffmpeg 提取帧失败: %w", err)
    }

    // 收集所有帧文件
    entries, _ := os.ReadDir(outputDir)
    var frames []string
    for _, e := range entries {
        if strings.HasSuffix(e.Name(), ".jpg") {
            frames = append(frames, filepath.Join(outputDir, e.Name()))
        }
    }
    return frames, nil
}

// 获取视频总时长(秒)
func getVideoDuration(videoPath string) (float64, error) {
    cmd := exec.Command("ffprobe",
        "-v", "error",
        "-show_entries", "format=duration",
        "-of", "default=noprint_wrappers=1:nokey=1",
        videoPath,
    )
    out, err := cmd.Output()
    if err != nil {
        return 0, err
    }
    return strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
}

一个 40 分钟的视频,每 30 秒一帧 = 80 帧。每帧约 100KB,总共 8MB------一张流量的量。


第二步:Vision API 描述每一帧

go 复制代码
import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "bytes"
)

type FrameDescription struct {
    FrameNum int
    Timestamp string // "MM:SS" 格式
    Description string
}

// 单帧描述
func describeFrame(imagePath string, frameNum int, timestamp string) (*FrameDescription, error) {
    data, _ := os.ReadFile(imagePath)
    b64 := base64.StdEncoding.EncodeToString(data)

    prompt := `请用一句话描述这张视频截图的画面内容(中文,不超过30字)。
只描述你看到的,不要推测。如果画面包含文字,把文字内容写出来。`

    // 调 Vision API(复用上一篇的 askWithImage)
    text, err := askWithImageBase64(b64, prompt)
    if err != nil {
        return nil, err
    }

    return &FrameDescription{
        FrameNum:    frameNum,
        Timestamp:   timestamp,
        Description: strings.TrimSpace(text),
    }, nil
}

// 批量处理,控制并发
func describeAllFrames(frames []string, intervalSec int) ([]FrameDescription, error) {
    results := make([]FrameDescription, len(frames))
    sem := make(chan struct{}, 3) // 并发 3 个请求

    for i, frame := range frames {
        sem <- struct{}{}
        go func(idx int, path string) {
            defer func() { <-sem }()
            ts := fmt.Sprintf("%02d:%02d",
                idx*intervalSec/60,
                idx*intervalSec%60,
            )
            desc, err := describeFrame(path, idx+1, ts)
            if err == nil {
                results[idx] = *desc
            } else {
                results[idx] = FrameDescription{
                    FrameNum: idx + 1,
                    Timestamp: ts,
                    Description: fmt.Sprintf("[处理失败: %v]", err),
                }
            }
        }(i, frame)
    }

    // 等待所有完成
    for j := 0; j < 3; j++ {
        sem <- struct{}{}
    }
    return results, nil
}

80 帧 × 3 并发 = 约 90 秒处理完(每帧 3 秒左右)。


第三步:LLM 串联成摘要

go 复制代码
func generateVideoSummary(descriptions []FrameDescription, duration float64) (string, error) {
    // 构建完整的帧描述文本
    var builder strings.Builder
    builder.WriteString(fmt.Sprintf("视频总时长: %d 分 %d 秒\n\n帧内容描述:\n",
        int(duration)/60,
        int(duration)%60,
    ))
    for _, d := range descriptions {
        builder.WriteString(
            fmt.Sprintf("[%s] 帧%d: %s\n", d.Timestamp, d.FrameNum, d.Description),
        )
    }

    prompt := fmt.Sprintf(`你是一个视频摘要助手。以下是每隔30秒提取的视频帧描述。
请根据这些描述生成:

## 视频主题
(一句话概括)

## 核心内容
(3-5 个要点,每个不超过 40 字,用 - 列出)

## 时间轴
(按时间段标注主要内容,如 [00:00-05:00] xxx)

## 一句话总结

如果某段时间没有有效信息(画面无变化或无法识别),标注为"画面静默/无变化"。

帧描述:
%s`, builder.String())

    return callLLM("你是一个视频摘要助手。准确、简洁、不要编造任何信息。", prompt)
}

实测结果

我拿一个 38 分钟的前端架构演讲视频做测试:

输入: 76 帧截图,每帧一行描述

输出摘要:

复制代码
## 视频主题
前端微前端架构从巨石应用到微前端的演进过程及工程化实践

## 核心内容
- 巨石应用 3 个痛点:构建慢、部署耦合、技术栈锁定
- Module Federation 实现运行时加载子应用
- 共享依赖策略:singleton vs shared
- 子应用间通信通过 EventBus,避免直接耦合
- 部署策略:独立构建 + 动态路由 + 灰度发布

## 时间轴
[00:00-08:00] 问题背景:为什么需要微前端
[08:00-18:00] 技术方案:Module Federation 原理演示
[18:00-28:00] 工程实践:代码组织 & 通信方案
[28:00-35:00] 部署 & 灰度发布
[35:00-38:00] 总结 & Q&A

## 一句话总结
微前端解决的不是技术问题,是组织协作问题。

对比实际看完视频的结论------完全正确。核心要点都抓到了,时间轴准确度在 ± 2 分钟内。


成本分析

步骤 数据量 成本
提取帧 38 分钟视频 → 76 张 JPEG 0(本地 ffmpeg)
Vision API 描述 76 帧 $0.01 × 76 ≈ ¥5.50
LLM 摘要 ~5000 token ¥0.005
合计 约 ¥5.50

比我自己花 38 分钟看完,省了 35 分钟,花了 5 块 5。这个 ROI 我自己觉得太值了。


优化技巧

  1. 跳过画面无变化的部分。 可以用 ffmpeg 的 scene 滤镜检测画面变化:select='gt(scene,0.1)'------只有变化超过 10% 的帧才保留。

  2. 优先识别带文字的画面。 演讲 PPT 画面比人脸画面有价值得多。可以先用简单的文字检测 skip 掉纯人脸的帧。

  3. 不只看画面,也读字幕。 结合 ffmpeg 字幕提取 + 画面帧描述 = 完整理解。字幕提取:

    bash 复制代码
    ffmpeg -i video.mp4 -map 0:s:0 output.srt

这个工具的核心价值

不是「自动看视频」这么简单。是可批量 + 可检索

你看完 100 个视频可能忘掉 80 个。但如果每个视频都有一份结构化摘要,你可以搜索「微前端 Module Federation 部署」,立刻找到所有相关视频和对应的时间点。

这也是我接下来要做的事------把我收藏的所有技术视频跑一遍,建一个可搜索的技术视频知识库。

下一篇进入一个更有趣的领域:让 AI 自己写代码、自己跑、看结果再调整。Code Interpreter。

相关推荐
searchforAI1 小时前
2026国产AI笔记工具横评:Get笔记、Ai好记、通义听悟、BiBiGPT各有什么特色?
人工智能·笔记·学习·ai·音视频·知识图谱·知识库
学术小白人1 小时前
【早鸟优惠】第二届AI赋能图像处理与计算机视觉技术国际学术研讨会(AIPCVT 2026)
大数据·人工智能·医学·数字能源·学术会议参会
咕咕AI学堂1 小时前
AI 任务调度算法:从优先级队列到公平调度的推理服务资源分配
人工智能
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-06-16
前端·人工智能·经验分享·chatgpt·html
guygg881 小时前
二维弹塑性有限元分析(von Mises 等向硬化)— MATLAB 实现
开发语言·人工智能·matlab
三千花灯2 小时前
【Playwright】 自动化测试之参数化登录(Excel/CSV 数据源)
人工智能·机器学习·excel
johnny2332 小时前
Agent记忆框架:MemPalace、Cognee、Hindsight、memories.ai
人工智能
YOLO数据集集合2 小时前
无人机风电设备智能巡检 风机叶片缺陷目标检测数据集实战 | 表面腐蚀漏油识别 工业视觉质检 深度学习模型训练落地10337期
人工智能·深度学习·目标检测·计算机视觉·无人机
zhenlai20122 小时前
Vue3 + SpringBoot + AI:我做了一个股票分析工具(第1周复盘)
人工智能·spring boot·后端