LLM —— 多模态(文本、图片、音频、视频)

作者:kishu_iOS&AI日期:2026/6/15

目录

一、什么是多模态

二、常见模态分类

三、多模态原理

单模态 vs 多模态

四、文本

五、图片

核心原理:

流程:

① 图像预处理(统一输入格式)

② 加载预训练视觉编码器

③ 前向传播,抽取特征向量

④ 向量归一化(L2 归一化,必做)

⑤ 持久化存储

方案代码:

关键细节

① 向量维度怎么选?

② 相似度计算方式

容易出错点

其他轻量化替代方案

六、音频

核心原理:

1.原始音频数据

2.从时域到频域的转换(频谱图)

3.声音数据怎么和时间关联?

① 采样率(Sampling Rate):定义时间精度

② 分帧(Framing):建立分析单元

4. 25MS与1/44100之间的关系?我人听见的是一个声音嘛?

5.方案代码:

方案 1:HuBERT 人声音频向量化(语音场景首选)

方案 2:CLAP 音频 - 文本跨模态向量化(语音 RAG 最强)

关键细节

① 池化方式选择

② 相似度计算

容易出错点

其他轻量化替代方案

七、视频

核心原理:

核销实现思路:

代码方案:

方案 1:CLIP 帧抽取 + CLAP 音频融合(最简通用,跨模态对齐)

方案2:X-CLIP(Video Transformer 编码器抽取视频向量)

关键细节

完整多模态视频编码器方案(视觉 Transformer + 音频编码器融合)

落地选型:


一、什么是多模态

模态就是信息的载体形式:文字、语音、图片、视频、表格、3D 模型、传感器信号等,每一类都叫一种模态。 多模态,就是模型 / 系统能同时接收、理解、生成、融合两种及以上不同类型的信息,不再只单一处理文字。

二、常见模态分类

  1. 文本模态:聊天文字、文档、代码、指令
  2. 音频模态:人声语音、背景音乐、环境音效
  3. 图像模态:照片、插画、截图、图纸
  4. 视频模态:连续画面 + 同步音频(图像 + 音频组合)
  5. 其他模态:点云、表格、PDF、体感动作、传感器数据

三、多模态原理

单模态 vs 多模态

  • 单模态 LLM:只能看文字,你发图片它看不懂,只能文字问答;
  • 多模态大模型:既能读文字、听语音、看图片、解析视频,还能跨模态互相转换。

多模态模型会用编码器(Encoder)把图片、音频、文字等不同格式信息,统一转换成同一维度的数值向量(嵌入表征),映射到同一个特征空间,让机器能统一对比、关联、推理不同模态信息,实现跨模态理解。

底层数据处理:

  1. 文本 → Text Encoder → Text Embedding
  2. 图片 → Image Encoder → Image Embedding
  3. 音频 → Audio Encoder → Audio Embedding
  4. 视频 → Video Encoder → Video Embedding

这些 Embedding 最终进入同一个向量空间

文本 / 图片 / 音频 / 视频 不同编码器 统一向量空间 向量数据库 多模态检索 大模型生成回答

四、文本

Markdown / PDS / 文档 -> 文本切片 -> Embedding -> 向量数据库

五、图片

图片 -> 图像编码模型 - > 图像向量 -> 向量数据库

核心原理:

原始图片是三维张量:【H高度,W宽度,3通道RGB】,RGB像素值 0 - 255.

② 用预训练 CNN / 视觉大模型(ResNet、CLIP、SigLIP 等)做特征提取

③ 去掉最后分类全连接层,取出模型中间输出的特征张量,做池化压缩成一维定长向量

④ 可选归一化,存入向量数据库(Milvus、FAISS、Chroma、Redis)做检索。

流程:

① 图像预处理(统一输入格式)

模型对输入图片有强制规范,必须标准化:

<1> 缩放裁剪:统一尺寸(如 224×224、384×384);

<2> 像素归一化:像素值从0~255映射到0~1,再用数据集均值、方差标准化;

<3> 通道调整:PIL 图片默认 RGB,排除 Alpha 透明通道;

<4> 转为模型要求张量格式:[batch, 3, H, W](PyTorch NCHW 格式)。

② 加载预训练视觉编码器

两大技术路线:

<1> 传统 CNN(ResNet/EfficientNet):只提取视觉特征,无法和文本向量对齐;

<2> CLIP/SigLIP(跨模态对齐模型):图片向量、文字向量处在同一个特征空间,图文互搜首选,工业主流。

③ 前向传播,抽取特征向量

<1> CNN:取全局平均池化 GAP 后的输出,直接得到一维向量;

<2> CLIP:调用image_encoder,返回图像 Embedding。

④ 向量归一化(L2 归一化,必做

向量每个元素除以自身 L2 范数,向量模长 = 1。 归一化后用余弦相似度计算图片相似度 等价于内积,向量检索速度大幅提升。

⑤ 持久化存储

定长浮点数组(如 768 维、512 维)存入向量库,后续可:

<1> 以图搜图

<2> 输入文字,转文本向量,检索相似图片。

方案代码:

方案1:CLIP 图片向量化(推荐,图文跨模态对齐)

1from PIL import Image
2import torch
3import numpy as np
4from transformers import CLIPProcessor, CLIPModel
5
6# 1. 加载模型与预处理工具
7model_name = "openai/clip-vit-base-patch32"
8model = CLIPModel.from_pretrained(model_name)
9processor = CLIPProcessor.from_pretrained(model_name)
10model.eval()
11
12# 2. 加载图片
13img = Image.open("test.jpg").convert("RGB")
14
15# 3. 预处理
16inputs = processor(images=img, return_tensors="pt")
17
18# 4. 推理提取图像向量(禁用梯度,提速省显存)
19with torch.no_grad():
20    img_emb = model.get_image_features(**inputs)
21
22# 5. L2归一化
23img_emb = img_emb / img_emb.norm(p=2, dim=-1, keepdim=True)
24
25# 6. 转为numpy一维向量(可直接入库)
26vec = img_emb.squeeze(0).numpy()
27print("向量维度:", vec.shape)  # clip-vit-base-patch32 输出512维
28print("前10个向量值:", np.round(vec[:10], 4))

方案2:ResNet 传统 CNN 图片向量化(纯视觉检索)

只提取图像特征,不能和文本匹配:

1from PIL import Image
2import torch
3import torchvision.models as models
4import torchvision.transforms as T
5import numpy as np
6
7# 1. 加载预训练ResNet,去掉最后分类层
8resnet = models.resnet50(pretrained=True)
9resnet.eval()
10# 截取到平均池化层,输出特征
11feature_extractor = torch.nn.Sequential(*list(resnet.children())[:-1])
12
13# 2. 标准化预处理
14transform = T.Compose([
15    T.Resize((224, 224)),
16    T.ToTensor(),
17    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
18])
19
20# 3. 图片处理+向量化
21img = Image.open("test.jpg").convert("RGB")
22img_tensor = transform(img).unsqueeze(0)
23
24with torch.no_grad():
25    feat = feature_extractor(img_tensor)
26
27# 展平+归一化
28vec = feat.squeeze().numpy()
29vec = vec / np.linalg.norm(vec)
30print("ResNet向量维度:", vec.shape)  # 2048维

关键细节

① 向量维度怎么选?

CLIP ViT-B/32:512 维(通用、速度快)

CLIP ViT-L/14:768 维(精度更高,占用存储翻倍)

ResNet50:2048 维,向量体积大,检索慢

② 相似度计算方式

归一化后两个图片向量vec1、vec2: 余弦相似度 = np.dot(vec1, vec2) 值越接近 1,图片内容越相似。

容易出错点

① 直接用像素数组当向量:像素受亮度、缩放、平移干扰,完全无法语义匹配;

② 不归一化就入库:余弦相似度计算失效,检索结果错乱;

③ 训练模式提取特征:没有torch.no_grad(),显存暴涨、向量波动不稳定。

其他轻量化替代方案

① OpenCLIP:优化版 CLIP,支持更多中文场景;

② Sentence-Transformers 封装的 CLIP:一行代码完成图片向量化;

③ 阿里云 / 腾讯云图片向量 API:无需本地部署模型,在线调用直接返回向量。

六、音频

音频向量化:把时域波形 / 频谱音频文件,编码成固定长度一维浮点嵌入向量(Embedding)。语义、音色、内容相近的音频,向量在特征空间距离更近,用于音频检索、声纹识别、语音 RAG、语音相似度比对、语音分类。

音频文件 → 重采样 + 单声道预处理 → CLAP/HuBERT 编码音频向量 → 归一化 → Milvus 向量库存储

① 上传新音频:编码向量,相似度检索召回相似音频片段;

② 输入文字描述:文本编码成同空间向量,直接检索对应音频。

核心原理:

音频数据化表示的整个过程,就像是把一个连续的、抽象的物理现象(声音),翻译成一个离散的、结构化的数字表格

1.原始音频数据

音频原始采样是一维时间序列:[采样点数,],数值是声波振幅,没法直接做相似度计算。

常见参数:采样率 16kHz、单声道、16bit 量化。(原始波形图

2.从时域到频域的转换(频谱图)

核心工具: 傅里叶变换(FFT)

转换目的: FFT 将一段很短的声音(例如 25 毫秒)分解为构成它的所有基本频率及其

  • 数据形态: 这产生了 频谱图(Spectrogram)
    • X 轴(时间): 保持不变,代表声音的持续时间。
    • Y 轴(频率): 替换了振幅,代表声音的音高(低频是低音,高频是高音)。
    • 颜色/亮度: 代表该频率的能量或强度(响度)。
  • 你可以这样理解: 这就像是把一首歌(波形图)分解成了所有单独的乐器及其各自的音量(频谱图)。
  • 频谱图是一种二维的、像图像一样的数字表格。

转换提取特征

波形信号转梅尔频谱 MFCC、梅尔语谱图 Mel-Spectrogram(CNN/Transformer 音频模型标准输入)

预训练音频编码器(Audio Encoder)映射为 Embedding 向量 音频特征送入预训练模型,去掉分类头,抽取全局特征,压缩成定长一维向量,可选 L2 归一化,存入向量库。

( 编码器对频谱图进行分帧,然后使用自监督学习将每一小块(一小段时间和频率范围)的特征压缩成一个高维的向量 )

最终进入 LLM 的就是这个序列,它与文本的 Tokens 序列是同一种结构

3.声音数据怎么和时间关联?

在 LLM 处理的音频数据中,连续的数字序列(声学特征向量序列)**是通过采样(Sampling)和分帧(Framing)**这两个步骤,被硬性地和时间关联起来的。

LLM 最终接收的音频数据形态是 $\text{向量}_{1}, \text{向量}_{2}, \text{向量}_{3}, \ldots$,这个序列之所以能代表时间,是因为在预处理阶段,我们建立了固定的时间参考系

① 采样率(Sampling Rate):定义时间精度

原始的连续声波必须转化为离散的数字信号。采样率定义了时间上的最小分辨率

<1> 机制: 计算机在每秒钟对声音的振幅(响度)进行固定次数的测量。

例如,CD 音质的采样率是 44,100 Hz,意味着每秒测量 44,100 次。

<2> 关联: 这意味着序列中的每一个原始数字点都代表了 1/44100 秒的时间。这建立了数据点和绝对时间之间的基础关联。

② 分帧(Framing):建立分析单元

在生成频谱图和声学特征向量之前,我们不会单独分析每一个采样点,而是将一小段连续的采样点打包成一个“帧”。

<1> 机制:将音频流切割成许多小的、有重叠的短帧(例如 25 毫秒)

<2> 关联: 每一个最终的特征向量都是从一个 25 毫秒的短帧中提取出来的

<3> 序列与时间: 由于这些帧是沿着原始时间轴顺序排列的

  • V1代表 0 毫秒到 25 毫秒的声音特征。
  • V2代表 10 毫秒到 35 毫秒的声音特征(通常帧之间有重叠)。
  • 这个向量序列的长度直接反映了音频的持续时间

总结: 连续的数字序列之所以能跟时间关联,是因为我们通过固定的采样率固定长度的分帧,将连续的时间流转化成了离散的、等间隔的数字单位

4. 25MS与1/44100之间的关系?我人听见的是一个声音嘛?

您的耳朵听到的声音在 25 毫秒内是连续的,但这并不妨碍计算机为了分析和识别,而将这 25 毫秒划定为一个固定的处理单元。

应用:

  1. 语音专属向量(人声、对话、ASR 配套 RAG):HuBERT、Wav2Vec2、Whisper(两种用法)

音频 -> ASR 语音识别 -> 文本 -> 文本向量化

2.跨模态对齐(音频↔文字):CLAP(音频版 CLIP),音频向量和文本向量同特征空间,语音搜文字、文字搜音频

音频不只有文字,还有声音特征。

比如:音色、语速、情绪、背景声音、音乐节奏、环境噪音

音频波形 -> 音频编码模型 -> 音频向量

模型输入向量用途向量维度特点
VGGish梅尔频谱音乐、环境音效检索128 维轻量老牌,仅音频内比对
Wav2Vec2 / HuBERT原始波形人声、语音内容表征768 维Facebook 语音专用,ASR 配套首选
Whisper梅尔频谱语音识别 + 同时提取音频特征1024 维可同时转文字 + 出向量
CLAP原始波形音频 - 文本跨模态检索512/768 维音频、文本向量同空间,语音 RAG 必备
5.方案代码:

环境:

pip install torch transformers librosa soundfile numpy

方案 1:HuBERT 人声音频向量化(语音场景首选)

只做人声内容向量化,适合语音知识库、语音片段检索

1import librosa
2import torch
3import numpy as np
4from transformers import HubertModel, Wav2Vec2Processor
5
6# 1. 加载模型&处理器
7model_name = "facebook/hubert-base-ls960"
8processor = Wav2Vec2Processor.from_pretrained(model_name)
9model = HubertModel.from_pretrained(model_name)
10model.eval()
11
12# 2. 加载音频,强制重采样到16kHz(模型固定输入)
13audio_path = "voice.wav"
14waveform, sr = librosa.load(audio_path, sr=16000)
15
16# 3. 预处理
17inputs = processor(
18    waveform,
19    sampling_rate=16000,
20    return_tensors="pt"
21)
22
23# 4. 推理提取特征,取全局均值池化得到单条向量
24with torch.no_grad():
25    outputs = model(**inputs)
26# last_hidden_state: [batch, time_step, hidden_dim]
27hidden_states = outputs.last_hidden_state
28# 时间维度均值池化,压缩为一维向量
29audio_emb = torch.mean(hidden_states, dim=1)
30
31# 5. L2归一化(向量检索必做)
32audio_emb = audio_emb / torch.norm(audio_emb, p=2, dim=-1, keepdim=True)
33vec = audio_emb.squeeze(0).numpy()
34
35print(f"向量维度:{vec.shape}")
方案 2:CLAP 音频 - 文本跨模态向量化(语音 RAG 最强)

音频向量和文本向量处在同一特征空间,支持:文字描述搜音频、音频搜匹配文本

1import librosa
2import torch
3import numpy as np
4from transformers import ClapModel, ClapProcessor
5
6model_name = "laion/clap-htsat-unfused"
7processor = ClapProcessor.from_pretrained(model_name)
8model = ClapModel.from_pretrained(model_name)
9model.eval()
10
11# 加载音频
12waveform, sr = librosa.load("audio.wav", sr=48000)
13
14# 音频编码
15audio_inputs = processor(audios=waveform, sampling_rate=48000, return_tensors="pt")
16with torch.no_grad():
17    audio_emb = model.get_audio_features(**audio_inputs)
18
19# 归一化
20audio_emb = audio_emb / audio_emb.norm(p=2, dim=-1, keepdim=True)
21audio_vec = audio_emb.squeeze(0).numpy()
22
23# 同步提取文本向量,可直接余弦匹配
24text_inputs = processor(text=["一段人声说话"], return_tensors="pt")
25with torch.no_grad():
26    text_emb = model.get_text_features(**text_inputs)
27text_emb = text_emb / text_emb.norm(p=2, dim=-1, keepdim=True)
28text_vec = text_emb.squeeze(0).numpy()
29
30# 计算音频-文本相似度
31sim = np.dot(audio_vec, text_vec)
32print("音频文本余弦相似度:", sim)

关键细节

① 池化方式选择

模型输出是时序特征 [时间步, 隐藏维度],必须压缩成单个定长向量:

  • 均值池化(推荐):整段音频全局表征,抗时长变化
  • 首尾 token:仅取第一个时间步,短音频尚可,长音频效果差
② 相似度计算

归一化后,余弦相似度 = 向量内积 np.dot(vec1, vec2),值域 [-1,1],越接近 1 音频内容越相似。

容易出错点

  • 采样率不匹配:Wav2Vec/HuBERT 强制 16kHz,音频不重采样向量完全失效
  • 不关闭梯度计算:torch.no_grad() 遗漏,显存占用极高、推理缓慢
  • 多声道音频:必须转单声道,模型仅支持单通道波形输入
  • 超长音频不截断:10 分钟以上长音频时序过长,内存溢出,建议分段编码、分段入库

其他轻量化替代方案

① 无需本地 GPU:调用阿里云、百度智能云音频向量 API,直接 HTTP 接口返回向量;

② 批量处理:循环遍历音频文件夹,批量生成向量批量导入 FAISS/Milvus。

七、视频

核心原理:

视频的本质 = 1s 60张图 + 声音

LLM理解视频就是理解 图片+声音

怎么理解时间线?

transformer天生自左向右????

给LLM学习向量(图片1、音频1、图片2、音频2、图片3、音频3)

LLM 学习并识别视频是一个复杂的多模态任务,因为它必须同时处理空间信息(图像内容)、时间信息(动作变化)以及音频信息(声音内容)。它通过将视频的不同维度分解并转化为统一的向量序列来实现学习。

———————————————————————————————————————————

LLM 处理视频的关键在于时空分解和跨模态对齐。

A. 空间编码 (Spatial Encoding - 内容)

处理: 视频的每一帧都被视为一张独立的图像。它通过 Vision Transformer (ViT) 类似的架构,被切分成 图像块(Patches),并转化为视觉特征向量序列。

目的: 识别视频中每一瞬间的内容,例如画面中的人、物体、背景等。

B. 时间编码 (Temporal Encoding - 动作)

处理: 专门的时间编码器(或基于 Transformer 的时序层)会分析连续多帧的特征向量序列。

目的: 学习帧与帧之间的变化关系和动作流。这使得模型能够识别出事件和动作(如“跑动”、“说话”、“物体移动”),而不是孤立的静态图像。

音频编码与多模态同步

视频通常包含音频流,这需要单独处理并与视觉信息对齐:

音频编码: 视频中的声音被提取,经过采样、分帧等处理,转化为声学特征向量序列(类似于 LLM 学习音频的过程)。

同步对齐: LLM 通过训练学习将视觉动作(如嘴唇的开合序列)与音频序列(如说话的声音)进行同步关联。这使得模型能进行语音识别、唇语解读以及理解背景音。

———————————————————————————————————————————

统一的时空序列处理

经过编码,LLM 的核心 Transformer 接收到的是一个巨大的、复杂的时空序列

$$\text{LLM 输入} = [\text{文本指令}] + [\text{帧 1 视觉/时间特征}] + [\text{帧 2 视觉/时间特征}] + \ldots + [\text{音频特征}]$$

  • 自注意力机制: 在这个统一的序列中,模型的自注意力机制必须同时在 图像块之间、时间帧之间、以及视觉和文本之间****计算关联性
  • 推理生成: 模型在理解了所有输入模态后,能够生成复杂的推理答案,例如:“根据视频中人物的动作和声音,他们接下来可能会去厨房。”

总结来说,LLM 学习视频是基于解构-编码-对齐的原则,将连续的视频流转化为一个它能处理的统一数字语言序列

核销实现思路:

① 拆分成「帧图像 + 音频」分别编码,再融合(工业最常用)

视频拆解:

  1. 均匀抽取关键帧(多张图片)→ 图像编码器(CLIP/SigLIP)得到帧向量
  2. 分离视频音轨 → 音频编码器(CLAP/HuBERT)得到音频向量
  3. 时序聚合 + 特征融合,拼接 / 加权融合成单个全局视频向量

② 端到端视频专用 Transformer 模型(直接输入视频片段)

VideoCLIP、X-CLIP、InternVideo、TimeSformer 等视频原生模型,一次性输入连续帧序列,自带时序建模,直接输出全局视频向量,画面动态变化、镜头运动、时序逻辑都能捕捉。

标准流程:
视频解析:ffmpeg 提取视频流、音频流;按固定间隔抽关键帧(每秒 1 帧 / 每 3 秒 1 帧,避免冗余)

② 模态预处理

<1> 帧:统一分辨率、归一化,适配图像编码器

<2> 音频:重采样到 16kHz/48kHz、转单声道

③ 分模态编码得到子向量

<1> 多帧图像:每帧单独编码向量,做时序均值 / 最大池化,得到画面全局向量

<2> 音轨:编码得到音频全局向量

④ 特征融合

方式 1:直接拼接(画面向量 + 音频向量,维度叠加)

方式 2:加权求和(设置画面权重 α、音频权重 1-α)

方式 3:全连接层映射到统一固定维度

L2 归一化,最终得到单个定长视频向量

⑥ 存入 Milvus/FAISS 做向量检索

代码方案:

方案 1:CLIP 帧抽取 + CLAP 音频融合(最简通用,跨模态对齐)

优势:不用训练视频模型,复用成熟图文、音文对齐模型,视频向量还能和文本向量做跨模态检索(文字搜视频)。

1pip install torch transformers opencv-python librosa soundfile ffmpeg-python numpy
2
1import cv2
2import librosa
3import torch
4import numpy as np
5from transformers import CLIPModel, CLIPProcessor, ClapModel, ClapProcessor
6
7# 设备
8device = "cuda" if torch.cuda.is_available() else "cpu"
9
10# 1. 加载图像、音频编码模型
11clip_name = "openai/clip-vit-base-patch32"
12clip_model = CLIPModel.from_pretrained(clip_name).eval().to(device)
13clip_processor = CLIPProcessor.from_pretrained(clip_name)
14
15clap_name = "laion/clap-htsat-unfused"
16clap_model = ClapModel.from_pretrained(clap_name).eval().to(device)
17clap_processor = ClapProcessor.from_pretrained(clap_name)
18
19def extract_video_frames(vid_path, sample_rate=1):
20    """抽帧:每秒取1帧"""
21    cap = cv2.VideoCapture(vid_path)
22    fps = cap.get(cv2.CAP_PROP_FPS)
23    frame_interval = int(fps / sample_rate)
24    frames = []
25    idx = 0
26    while True:
27        ret, frame = cap.read()
28        if not ret:
29            break
30        if idx % frame_interval == 0:
31            rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
32            frames.append(rgb)
33        idx += 1
34    cap.release()
35    return frames
36
37# ---------------------- 1. 画面向量化 ----------------------
38video_path = "test.mp4"
39frames = extract_video_frames(video_path, sample_rate=1)
40# 逐帧编码
41frame_embs = []
42with torch.no_grad():
43    for img in frames:
44        inputs = clip_processor(images=img, return_tensors="pt").to(device)
45        emb = clip_model.get_image_features(**inputs)
46        emb = emb / emb.norm(p=2, dim=-1, keepdim=True)
47        frame_embs.append(emb)
48# 时序均值池化,得到全局画面向量
49frame_stack = torch.cat(frame_embs, dim=0)
50vis_emb = frame_stack.mean(dim=0, keepdim=True)
51
52# ---------------------- 2. 音频向量化 ----------------------
53audio_wave, sr = librosa.load(video_path, sr=48000)
54audio_in = clap_processor(audios=audio_wave, sampling_rate=48000, return_tensors="pt").to(device)
55with torch.no_grad():
56    aud_emb = clap_model.get_audio_features(**audio_in)
57aud_emb = aud_emb / aud_emb.norm(p=2, dim=-1, keepdim=True)
58
59# ---------------------- 3. 融合得到最终视频向量 ----------------------
60# 方式1:拼接融合
61video_emb_cat = torch.cat([vis_emb, aud_emb], dim=-1)
62# L2归一化
63final_emb = video_emb_cat / video_emb_cat.norm(p=2, dim=-1, keepdim=True)
64video_vec = final_emb.squeeze(0).cpu().numpy()
65
66print(f"最终视频向量维度:{video_vec.shape}")
方案2:X-CLIP(Video Transformer 编码器抽取视频向量)

pip install torch transformers opencv-python pillow numpy

1import cv2
2import torch
3import numpy as np
4from transformers import XCLIPProcessor, XCLIPModel
5
6device = "cuda" if torch.cuda.is_available() else "cpu"
7
8# 加载X-CLIP:视频专用Transformer编码器
9model_name = "microsoft/xclip-base-patch32-frames16"
10processor = XCLIPProcessor.from_pretrained(model_name)
11model = XCLIPModel.from_pretrained(model_name).eval().to(device)
12
13def sample_video_frames(vid_path, num_frames=16):
14    """均匀采样固定帧数,适配X-CLIP输入要求"""
15    cap = cv2.VideoCapture(vid_path)
16    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
17    frame_indices = np.linspace(0, total_frames-1, num_frames, dtype=int)
18    frames = []
19    for idx in frame_indices:
20        cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
21        ret, frame = cap.read()
22        if ret:
23            rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
24            frames.append(rgb)
25    cap.release()
26    return frames
27
28# 1. 读取视频+采样帧
29frames = sample_video_frames("test.mp4", num_frames=16)
30# 2. Transformer编码器预处理
31inputs = processor(
32    videos=frames,
33    return_tensors="pt"
34).to(device)
35
36# 3. Video Transformer前向推理,提取视频全局向量
37with torch.no_grad():
38    out = model(**inputs)
39video_emb = out.video_embeds
40
41# L2归一化
42video_emb = video_emb / video_emb.norm(p=2, dim=-1, keepdim=True)
43video_vec = video_emb.squeeze(0).cpu().numpy()
44
45print(f"Video Transformer输出向量维度:{video_vec.shape}")

关键细节

① 相比「CLIP 抽帧 + 手动融合」的优缺点

优点:

<1> Transformer 原生建模时序运动,能区分「人抬手→人放下手」这类动态差异;逐帧 CLIP 只能看单张画面,分不清动作顺序

<2> 端到端一键输出视频向量,不用分别处理画面、音频、手动拼接加权

<3> X-CLIP 等双塔结构天然和文本向量对齐,直接支持文搜视频

缺点:

<1> 输入必须固定帧数,长视频需要切片

<2> 参数量更大,推理速度比单帧 CLIP 慢

<3> 不自带音频建模,纯视觉 Video Transformer 听不到视频声音

完整多模态视频编码器方案(视觉 Transformer + 音频编码器融合)

真实业务落地标准链路: 视频 → 视觉流送入X-CLIP(Video Transformer) 得到视觉向量 视频 → 分离音轨送入 CLAP 得到音频向量 向量加权 / 拼接融合 → 归一化 → 最终完整多模态视频向量入库

落地选型:

  • 仅视觉检索、动作识别:TimeSformer
  • 视频检索、文搜视频、视频 RAG:X-CLIP(首选)
  • 长视频精读、视频问答:InternVideo2
  • 轻量化场景:依旧可以用「CLIP 抽帧均值池化」,牺牲时序精度换速度

LLM —— 多模态(文本、图片、音频、视频)》 是转载文章,点击查看原文


相关推荐


别再乱套ScrollViewer了!WPF中ItemsControl滚动条失效的3个隐藏坑与终极修复方案
许筱淳2026/6/8

WPF中ItemsControl滚动条失效的深度剖析与实战解决方案 当你在WPF项目中遇到ItemsControl滚动条"罢工"时,是否也经历过这样的场景:明明按照标准做法添加了ScrollViewer,滚动条却像被施了隐身术一样消失不见?或者鼠标滚轮在嵌套控件中滑动时毫无反应?这些问题往往源于WPF视觉树和事件路由机制的深层特性。本文将带你深入这些"坑"的本质,并提供真正有效的解决方案。 1. 为什么简单的ScrollViewer包裹会失效? 许多开发者第一次遇到ItemsControl


python爬虫-基本库-urllib库(常用速查)
bigfootyazi2026/6/1

urllib库 库的用途四个基本模块request模块error模块parse模块robotparser模块 库的用途 实现HTTP请求的发送 扩展:基本HTTP库有urllib、requests、httpx等 四个基本模块 request 基本的HTTP请求模块error 异常处理模块parse 工具模块,提供URL的处理方法robotparser 识别网站的robost.txt文件 request模块 urlopen (function) def urlopen(


📱随时随地大小编:TraeSolo 移动端初体验
海石2026/5/12

1、前言 最早认识Trae SOLO 还是在Trae IDE 内测 SOLO 模式的时候 (大概是2025年的11月) 这一转眼,Trae SOLO 居然都已经单独出了 桌面端 和 移动端 了 除了劳动节那阵联动星巴克☕吸引我之外不是 咳咳,最有魅力的还是双端协同这一点上 本文就是一篇“利用Trae SOLO的双端协同能力,进行随时随地开发微信小程序”的实践分享文章, 非常欢迎掘友们一起交流交流,共同探讨Trae SOLO的最佳使用“范式”~ 2、结果先行 1、移动端可以随时查看微信


window管理开发环境篇 - 持续更新
pe7er2026/5/2

我个人非常喜欢那种一键部署开发环境的方式,但时间一长,我们会淡忘如何部署开发环境,它会让我们失去对开发环境的控制。 下面我记录window环境下我是如何管理开发环境的。 安装Scoop 设置前提条件 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser 典型安装 irm get.scoop.sh | iex 使用代理安装 iex "& {$(irm get.scoop.sh -Proxy 'http://<ip:


NineData 新增支持 GaussDB 到 StarRocks 实时数据复制能力
NineData2026/4/23

很多企业在完成核心系统国产化之后,业务已经稳定跑在 GaussDB 上,但很快会进入下一阶段:经营分析、实时看板、主题查询、风控报表、数据服务层都需要尽快接上。 如何实现呢?把业务数据实时复制到数仓即可。但通常会有如下挑战: 历史数据需要快速初始化到位。 业务持续写入时,目标端要持续、稳定地追平变化。 任务运行出了问题,要能第一时间感知,如果等到下游发现数据不对那就晚了。 正式上线前,要能全自动化对复制结果做核验,人工抽样费时费力还容易出错。 这个时候,一条能长期稳定的实时数据复制链路就很


告别 Python 依赖!用 LangChainGo 打造高性能大模型应用,Go 程序员必看!
GetcharZp2026/4/14

想用 Go 语言开发大模型应用却找不到好用的框架?本文深度解析 LangChainGo,手把手教你快速上手,涵盖 RAG、智能体等核心场景,助你轻松跨入 AI 开发大门! 在人工智能大行其道的今天,提到 LLM(大语言模型)应用开发,很多人脑海中浮现的第一反应就是 Python。确实,Python 拥有得天独厚的生态。但随着 AI 应用进入“工程化”下半场,开发者们开始面临新的挑战:并发性能瓶颈、部署环境复杂、内存消耗大…… 这时候,Go 语言的优势便凸显了出来。其天生的并发处理能力(Gor


**发散创新:基于以太坊侧链的高性能去中心化应用部署实战**在区块链生态中,*
好家伙VCC2026/4/6

发散创新:基于以太坊侧链的高性能去中心化应用部署实战 在区块链生态中,主链性能瓶颈一直是制约大规模 DApp 发展的核心问题。为突破这一限制,8*侧链(Sidechain)技术应运而生**,它通过与主链的安全通信机制,在保证去中心化前提下实现高吞吐量和低延迟交易处理。 本文将以 Solidity + Golang + Polygon SDK 为例,构建一个完整的侧链开发流程,并展示如何将智能合约部署到自定义侧链节点上,同时确保与 Ethereum 主网的状态同步验证。 🔧 一、为什么


彻底搞懂大模型 Temperature、Top-p、Top-k 的区别!
Surmon2026/3/29

调用大模型的时候,总会看到几个耳熟能详的参数:Temperature、Top-p、Top-k。文档里通常的解释都是:控制输出的随机性。也就是:Temperature 和 Top-p 的值越高,模型输出的结果会越随机、越富有创造性,反之,数值越低,输出的结果就越确定、越保守。 随机性,到底是个什么意思?为啥随机性就可以表现为创造性? 回答这个问题,得先从一个最朴素的问题开始:模型是如何回答问题的。 我之前在 《从统计学习到通用智能》 中曾经提到过,大模型在输出文本的时候,本质上是在 滚动地预测下


当我开始像写代码一样和AI对话,一切都变了
lbh2026/3/21

当AI成为你的开发伙伴,如何让它真正听懂你的需求? 身为一名前端开发。在日常开发中,我经常和AI打交道——用它写代码、调试bug、优化性能、设计方案。但说实话,很长一段时间里,我和AI的对话就像这样: 我:“帮我写一个响应式导航栏。” AI:(给出一个基础版) 我:“不是这样的,要带下拉菜单。” AI:(加上下拉菜单) 我:“还要在移动端变成汉堡菜单。” AI:(加上汉堡菜单) 我:“……能不能一次说完?” 你是不是也有类似的经历? 后来我慢慢发现,问题不在AI,而在我自己。就像写代码一样


使用Fetch API 探索前后端数据交互
独泪了无痕2026/3/13

前言   在当今的 Web 开发中,前端与后端的数据交互是构建动态应用的核心。API 是连接不同软件应用的重要桥梁,允许开发者通过 HTTP 请求与服务器交互,高效调用API数据对于构建现代 Web 应用至关重要。传统的页面刷新方式已经无法满足用户对流畅体验的需求,而 Fetch API 的出现为 JavaScript 带来了全新的生命力。 一、Fetch API 概述 1.1 Fetch API 是什么❓   Fetch API 是现代浏览器提供的一个用于发起网络请求的接口,用于发起 HTTP

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读