构建m3u8视频的智能语义检索系统

使用 OSS 的数据索引功能,可以对m3u8视频进行分析并实现语义检索并过滤,适用于m3u8视频智能搜索播放场景。

方案概览

image

搭建智能语义检索系统,只需三步:

  1. 创建 Bucket 并上传视频:创建用于存储视频文件的 Bucket,并上传待处理的视频文件,为后续视频检索提供有力支持。

  2. 开通过滤能力:配置 OSS 文件的过滤条件(如仅过滤以 .m3u8 结尾的文件)。配置完成后,系统仅为符合条件的文件建立索引,确保检索结果更聚焦、精准。

  3. 开启向量检索功能:为 Bucket 开启向量检索功能,以支持基于自然语言描述的智能检索。

方案优势

  • 语义化检索:支持基于自然语言描述和多条件组合的精准检索,能够快速定位目标画面,满足复杂场景下的检索需求。

  • 多模态检索:提供视频、图像、文本等数据统一管理与检索能力,降低技术门槛与运维成本。

  • 横向扩展:OSS 容量无限、弹性扩展,可轻松应对海量数据增长。

1. 创建Bucket并上传视频

  1. 登录OSS管理控制台

  2. 进入Bucket列表页面,并点击创建Bucket

  3. 创建Bucket页面,填写Bucket名称(建议使用业务相关的名称,如m3u8-videos-oss-metaquery-demo),其余参数可保持默认配置。

  4. 单击完成创建,在创建成功的页面,点击进入Bucket

  5. 文件列表页面,点击上传文件 > 扫描文件选择待上传的视频文件,其余参数保留默认配置,点击上传文件

2. 开通 MetaQuery 基于 Filters 的过滤能力

联系我们配置 OSS 文件的过滤条件(例如仅过滤以 .m3u8 结尾的文件)。配置完成后,当前 Bucket 仅会为符合条件的文件建立索引,其他文件不会被索引;检索时返回的结果也仅包含符合该过滤条件的文件。

Filters字段支持的变量和操作符

名称

类型

支持的操作符

描述

过滤示例值

Size

整型

= :等于,等同于==

!= :不等于

> :大于

>= :大于等于

< :小于

<= :小于等于

文件大小过滤。

  • Size > 9 :文件大小大于9

Filename

字符串

= :等于,等同于==

!= :不等于

prefix :包含前缀

suffix :包含后缀

in :在集合中

notin :不在集合中

文件名过滤。文件名需要经过URL safeBase64编码

  • Filename == YWEvYmIvY2MuanBn :文件名为 aa/bb/cc.jpg

  • Filename != YWEvYmIvY2MuanBn:文件名不为 aa/bb/cc.jpg

  • Filename notin (YWEvYmIvY2MuanBn, YWEvYmIvZGQuanBn):文件名不为 aa/bb/cc.jpg 或 aa/bb/dd.jpg

  • Filename in (YWEvYmIvY2MuanBn, YWEvYmIvZGQuanBn:文件名为 aa/bb/cc.jpg 或aa/bb/dd.jpg。

  • Filename prefix (YWEvYmIv, YWEvY2Mv):文件名前缀为“aa/bb/”或“aa/cc/”

  • Filename suffix (LmpwZw, LnBuZw):文件名后缀为“.jpg”或“.png”

FileModifiedTime

字符串

= :等于,等同于==

!= :不等于

> :大于

>= :大于等于

< :小于

<= :小于等于

文件修改时间过滤,使用RFC3339 时间格式。

  • FileModifiedTime > 2025-06-03T09:20:47.999Z :文件时间大于2025-06-03T09:20:47.999Z

OSSTagging.*

字符串

= :等于,等同于==

!= :不等于

! :不存在key

exists :存在key

prefix :包含前缀

suffix :包含后缀

in :在集合中

notin :不在集合中

标签过滤。标签的KeyValue都需要URL safeBase64编码

  • OSSTagging.Zm9v == YWJj:存在标签 Key 为“foo”且其 Value 为 “abc”

  • !OSSTagging.Zm9v:不存在标签 Key 为“foo”

  • OSSTagging.Zm9v:存在标签 Key 为 “foo”

    说明

    无需使用 exists 关键字,仅填写 Key 即可

  • OSSTagging.Zm9v in (YWJj, ZWZn):存在标签 Key 为 “foo”,Value 值为 “abc” 或“efg”

  • OSSTagging.Zm9v prefix (YWEvYmIv, YWEvY2Mv):存在标签 Key 为 “foo”,且其 Value 的前缀为 “aa/bb/” 或 “aa/cc/”

3. 开启向量检索功能

Bucket开启向量检索功能,支持对视频进行基于自然语言描述和多条件组合的精准检索。

  1. 在左侧导航栏, 选择文件管理 > 数据索引

  2. 数据索引页面,单击立即开启

  3. 选择向量检索,单击确认开启

说明

构建元数据索引需要等待一定的时间,具体等待时长取决于BucketObject的数量。若开启时间过久可通过刷新来查看开启状态。

image

image

结果验证

您只需输入描述性文字,例如停着车的院子,系统便会返回与描述相符的关键视频。

  1. Bucket 列表页面,点击您的 Bucket名称。

  2. 文件列表页面,确认视频已上传。

  3. 在左侧导航栏, 选择文件管理 > 数据索引

  4. 数据索引页面,检索内容中输入停着车的院子,在多媒体类型中勾选视频,点击立即查询

  5. 复制查询到的文件路径,返回文件列表页面,输入复制的文件路径进行搜索,即可查看到符合描述的视频。

2025-05-23_16-31-58 (1)

应用于生产环境

当前智能语义检索系统已经完成构建,为了将该系统无缝集成到您的产品并应用于生产环境,您可以通过调用应用接口,利用自然语言描述进行检索,快速定位目标事件。

以下为示例代码,展示如何构建符合 OSS MetaQuery 规范的 XML 请求,获取检索结果:

示例代码

# -*- coding: utf-8 -*-
import argparse
import alibabacloud_oss_v2 as oss
# 解析XML响应
import xml.etree.ElementTree as ET
import json 
from datetime import datetime 

def get_search_conditions():
    """获取用户的多条件输入"""
    print("请输入语义描述(示例:停着车的院子)")
    query = input("> 语义关键词: ").strip()
    while not query:
        print("语义关键词不能为空!")
        query = input("> 语义关键词: ").strip()
    return query  

def build_metaquery_xml(query):
    """构建符合OSS规范的MetaQuery XML"""
    xml_parts = [f'<Query>{query}</Query>']

    meta_query_xml = f'''<MetaQuery>
    {"".join(xml_parts)}
</MetaQuery>'''
    return meta_query_xml  # 编码为UTF-8字节流


def format_result(key, pre_url):
    """格式化单个搜索结果"""
    return f""" 文件路径:{key}
 文件地址:{pre_url}
-----------------------"""

def semantic_search():
    # 直接赋值给命令行参数
    args = argparse.Namespace(
        region='cn-beijing',  # 替换为你的区域
        bucket='m3u8-frames-oss-metaquery-demo',  # 替换为你的存储空间名称
        endpoint='https://oss-cn-beijing.aliyuncs.com',  # 替换为你的endpoint,如果不需要可以留空或删除
    )

    # 初始化OSS客户端
    credentials = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials
    cfg.region = args.region
    if args.endpoint:
        cfg.endpoint = args.endpoint
    client = oss.Client(cfg)

    # 获取用户输入
    query = get_search_conditions()  # 只获取查询
    # 构建请求
    try:
        # 构造请求体(XML 数据)
        data_str = build_metaquery_xml(query)  # 不再传递条件

        # 定义操作输入
        req = oss.OperationInput(
            op_name='DoMetaQuery',  # 自定义操作名称
            method='POST',            # HTTP 方法
            parameters={              # 查询参数
                'metaQuery': '',
                'mode': 'semantic',
                'comp': 'query',
            },
            headers=None,             # 自定义请求头(可选)
            body=data_str.encode("utf-8"),  # 请求体(编码为 UTF-8 字节流)
            bucket=args.bucket,       # 目标 Bucket 名称
        )

        # 调用泛化接口执行操作
        resp = client.invoke_operation(req)

    except oss.exceptions.ServiceError as e:
        print(f" 服务端错误:{e.message}")
        return
    
    root = ET.fromstring(resp.http_response.content.decode('utf-8'))
     # 查找所有File元素
    files = root.findall('.//File')
    
    print(f"\n 共找到 {len(files)} 个匹配结果:")
    


    for i, file in enumerate(files, 1):
        # 获取文件名
        key_element = file.find('Filename')
        if key_element is None:
            continue  # 如果没有找到文件名,则跳过当前循环迭代
        key = key_element.text
        
        
        # 生成预签名URL
        pre_url = client.presign(
            oss.GetObjectRequest(
                bucket=args.bucket,  # 指定存储空间名称
                key=key,        # 指定对象键名
            )
        )
        
        print(format_result(key, pre_url.url))
        
    

if __name__ == "__main__":
    semantic_search()

运行该程序后,您可以输入描述性文字(例如停着车的院子)进行查询。由于仅处理了过滤以.m3u8结尾的视频,因此最终检索结果仅包含视频 playlist.m3u8。