1. 项目概述与核心价值

在当前的流媒体服务生态中,个性化推荐早已不是什么新鲜概念。无论是首页的“猜你喜欢”,还是根据观看历史生成的“为你推荐”列表,其背后都是复杂的算法在分析我们的每一次点击、暂停和快进。然而,当我们把目光聚焦到电影预告片这个看似微小的环节时,会发现一个有趣的现象:绝大多数电影至今仍在使用“一刀切”的官方预告片。无论你是动作片狂热爱好者,还是钟情于细腻的情感叙事,你看到的《疾速追杀》或《爱乐之城》的预告片,很可能和全球数百万其他用户看到的别无二致。

这引出了一个核心矛盾:预告片作为用户决定是否投入两小时观看一部电影的关键“敲门砖”,其个性化程度却远远落后于其他推荐环节。传统的解决方案是将这个任务交给云端服务器——收集你的所有观看数据、互动行为,在强大的数据中心里进行分析和视频剪辑,再将生成的个性化预告片推送给你。这听起来很美好,但背后是沉重的代价:巨大的服务器计算开销、高昂的带宽成本,以及最令人不安的——用户隐私数据的集中暴露风险。

我最近深入研究并实践了一种截然不同的思路: 客户端驱动的个性化预告片生成框架 。这个项目的核心思想是“将计算还给边缘”。它不再依赖云端分析完整的电影视频流,而是利用一种轻量级的数据载体—— 缩略图容器 ,在用户的本地设备(如手机、平板、智能电视)上,实时完成用户感兴趣动作的识别与预告片序列的组装。简单来说,服务器只提供最原始的“素材包”(电影分片和对应的缩略图合集),而“剪辑师”的工作,完全在你的设备上,根据你即时选择的兴趣点(比如“马术”、“射门”)自动完成。

这种方法的价值是双重的。 首先,它是对用户隐私的极大尊重 。你的兴趣偏好、你对哪些镜头多看了一眼,这些数据无需离开你的设备,直接在本地处理完毕。 其次,它实现了惊人的计算资源优化 。处理一张160x90像素的缩略图,与解码一段数兆字节的1080p视频片段,所需的计算量是天壤之别。这使得在算力有限的移动设备上实现实时、个性化的视频内容生成成为可能。对于希望构建可扩展、低成本且符合日益严格数据法规的流媒体平台而言,这无疑提供了一条极具吸引力的技术路径。

2. 系统架构与核心设计思路

要理解这套框架为何高效,我们需要先拆解其整体架构。整个系统可以清晰地划分为服务器端和客户端两部分,其设计哲学是 职责分离与边缘智能

2.1 服务器端:轻量化的内容分发者

服务器的角色被极大地简化了,它不再是一个复杂的视频分析引擎,而是一个高效、标准化的内容分发者。其核心任务有两个:

  1. 提供视频流 :将电影编码成符合HLS标准的MPEG-2传输流片段,并生成对应的 .m3u8 播放列表。这是现代流媒体服务的通用做法,确保了广泛的客户端兼容性。
  2. 提供“视觉索引” :生成并存储与电影时间轴严格对应的 缩略图容器 。这是本框架的创新关键。

缩略图容器的生成过程 是服务器端唯一的预处理工作,但它的设计非常巧妙。以一篇典型的实践为例,我们使用FFmpeg工具,从电影中每秒提取一帧关键画面。接着,并非将这些图片单独存储,而是将25张缩略图(每张代表1秒)以5x5的网格排列,合并成一张稍大的“容器”图片。这样,一张800x450像素的容器图片,就承载了25秒电影内容的视觉摘要。

注意 :选择5x5的网格和每秒一帧的采样率并非随意决定。这借鉴了YouTube等主流平台的经验,在提供足够时间分辨率预览和保持单张图片尺寸极小之间取得了平衡。一张容器图片的大小通常只有几十KB,传输25秒的视觉信息,其带宽消耗远低于一秒钟的视频数据。

服务器采用 HTTP/2持久连接 来同时传输这些视频片段和缩略图容器。与传统的HTTP/1.1每次请求都建立新连接的方式不同,持久连接允许在单个TCP连接上并行处理多个请求和响应。这显著减少了建立连接的开销(如TCP三次握手、TLS协商),降低了服务器和客户端的CPU占用,尤其在高并发、频繁请求小文件(如众多.ts片段和缩略图容器)的场景下,性能提升非常明显。

2.2 客户端:智能化的内容消费者与生产者

客户端是本框架的“大脑”,它承担了从内容消费到内容生产的全过程。其工作流是一个清晰的闭环:

  1. 内容获取与解析 :客户端播放器根据 .m3u8 列表请求视频流。同时,它并行请求该电影对应的所有缩略图容器文件。
  2. 兴趣表达 :通过一个简单的Web界面,用户可以从一个预定义的动作标签列表(如“板球投球”、“马术骑行”)中选择自己当前感兴趣的类型。这个选择是即时、轻量的交互。
  3. 本地化智能分析 :这是核心步骤。客户端利用一个预先训练好的轻量级深度学习模型(例如基于MobileNet或EfficientNet优化的模型),对下载的缩略图容器进行“扫描”。客户端会从容器中裁剪出每一张独立的缩略图,然后将其输入模型,判断该秒的画面是否包含用户选择的动作。
  4. 时间戳映射与序列生成 :当识别出包含目标动作的缩略图后,系统能立刻映射回该画面在电影中的精确时间点(例如,第12张缩略图对应电影第305秒)。所有识别出的时间点被汇总、排序,并去除过于密集的重复点,形成一个“精彩时刻”时间戳列表。
  5. 个性化流组装 :客户端不再按顺序请求整个电影流,而是根据生成的时间戳列表,向服务器发起针对性的请求,只获取包含这些精彩时刻的短视频片段(HLS Segment)。最后,客户端在本地将这些片段无缝拼接,渲染成一个完整的、个性化的电影预告片。

这个设计的精妙之处在于, 沉重的模型推理计算发生在客户端,但消耗的是极轻量的输入数据(缩略图) 。服务器完全不知道用户喜欢什么,也不知道客户端拼接出了怎样的预告片,它只是按需提供了原始的“乐高积木”。隐私保护和计算卸载的目标由此同时实现。

3. 核心组件深度解析与实操要点

理解了宏观架构,我们深入到几个关键组件的实现细节和选型考量。这些细节决定了系统的可行性、效率和用户体验。

3.1 缩略图容器的工程化生成

缩略图容器是本系统的数据基石。其生成流程虽然不复杂,但有几个工程要点需要把握:

采样策略与分辨率选择

  • 采样率(每秒帧数) :采用每秒1帧(1 FPS)是权衡后的结果。更高的采样率(如5 FPS)能提供更精细的预览,但会线性增加容器图片的数量和客户端处理量。对于大多数电影叙事节奏,1 FPS已能有效捕捉场景转换和关键动作。
  • 缩略图分辨率 :选择160x90像素,这是一个经过验证的“黄金尺寸”。它足够小,单张图片仅约几KB,25张合并后容器图片也在100KB以内;同时,它也足够大,能让经过训练的神经网络从中提取有效的空间特征来识别动作。
  • 容器布局 :5x5网格是最优解。它使得单张容器图片的信息密度高(25秒),同时图片尺寸(800x450)仍在常规范围内,便于网络传输和客户端使用Canvas API进行快速裁剪。

实操命令示例(使用FFmpeg)

# 1. 提取每秒一帧的图片序列
ffmpeg -i input_movie.mp4 -vf fps=1 -q:v 2 thumbnails/thumb_%04d.jpg

# 2. 使用图像处理库(如Python PIL)将每25张图片拼接为5x5网格
# 这是一个简化的Python脚本逻辑
from PIL import Image
import os

thumb_size = (160, 90)
container_size = (800, 450) # 5*160, 5*90
thumbs_per_container = 25

for i in range(0, total_thumbnails, thumbs_per_container):
    new_im = Image.new('RGB', container_size)
    for row in range(5):
        for col in range(5):
            idx = i + row * 5 + col
            if idx < total_thumbnails:
                im_path = f'thumbnails/thumb_{idx:04d}.jpg'
                im = Image.open(im_path)
                im.thumbnail(thumb_size, Image.Resampling.LANCZOS)
                new_im.paste(im, (col * thumb_size[0], row * thumb_size[1]))
    new_im.save(f'containers/container_{i//thumbs_per_container:04d}.jpg')

3.2 客户端动作识别模型的选择与优化

在客户端进行实时动作识别,对模型有苛刻的要求:必须足够轻量以实现快速推理,又必须足够准确以提供良好的用户体验。

模型选型考量

  • 输入特性 :我们的输入是静态的缩略图,而非视频序列。因此,我们本质上进行的是 图像分类 任务,而非复杂的时空动作识别。这大大降低了模型复杂度。
  • 轻量化模型 :在资源受限的客户端,不能使用庞大的3D卷积网络或双流网络。经过微调的 2D图像分类网络 是更合适的选择。例如,MobileNetV3、EfficientNet-Lite或ShuffleNetV2,这些模型专为移动和边缘设备设计,在精度和速度间取得了良好平衡。
  • 训练数据适配 :虽然UCF-101是经典的动作识别数据集,但它包含的是视频。我们需要将其转化为适用于本任务的训练数据。通常的做法是从每个动作类别的视频中,均匀采样多帧静态图片,并为这些图片打上该动作的标签。这样,模型学习的是从单帧画面中识别出动作的“关键姿态”或“场景特征”。

模型部署与推理优化

  1. 模型转换 :将训练好的PyTorch或TensorFlow模型转换为适合客户端运行的格式,如TensorFlow.js模型用于Web环境,或TFLite模型用于原生移动应用。
  2. 预热与缓存 :在用户首次选择动作时加载模型会有延迟。可以在应用初始化阶段或空闲时预加载模型。识别出的时间戳列表也可以在本地缓存,避免用户重复选择相同动作时再次进行全片分析。
  3. 异步处理 :缩略图的分析不应阻塞主线程或影响视频播放。应使用Web Worker(浏览器环境)或后台线程(移动端)进行模型推理。

3.3 基于HLS的精准片段请求与拼接

这是将识别结果转化为最终视频流的关键步骤。HLS协议的特性使得这种“跳跃式”播放成为可能。

工作原理

  1. 时间戳映射 :假设识别出动作的时间点为 t 秒。
  2. 片段定位 :HLS的 .m3u8 播放列表指明了每个视频片段(通常为2-10秒)的时长和URL。客户端需要计算时间点 t 属于哪个片段(例如,第 N 个片段)。
  3. 构建个性化播放列表 :客户端不是请求原始完整的 .m3u8 ,而是在内存中动态生成一个新的 .m3u8 列表。这个新列表只包含那些包含了至少一个识别时间点的视频片段,并可能在这些片段的内部指定开始时间(利用HLS的 #EXT-X-BYTERANGE #EXT-X-MAP 结合 #EXT-X-DISCONTINUITY 标签来实现更精确的裁剪,但实现更复杂)。
  4. 播放器驱动 :将动态生成的个性化播放列表交给HLS播放器(如hls.js)。播放器会像播放普通流一样,按顺序请求并播放这些片段,从而实现无缝的预告片观看体验。

注意事项

  • 网络自适应 :HLS本身支持多码率。在请求个性化片段时,客户端播放器应依然能根据当前网速,选择请求高、中、低不同码率的版本,保证流畅性。
  • 缓冲区管理 :由于请求的片段在时间轴上可能不连续,播放器的缓冲区管理策略需要调整,避免因等待下一个“跳跃”的片段下载而导致卡顿。合理的预加载策略(提前下载后续的1-2个目标片段)很重要。

4. 完整实操流程与关键实现环节

让我们从一个开发者的视角,走一遍构建这个系统的核心流程。这里我会侧重于那些在论文之外,实际编码中会遇到的具体问题和解决方案。

4.1 环境搭建与基础数据准备

第一步:搭建本地HLS服务器 为了开发和测试,我们不需要庞大的媒体服务器。使用Nginx或Caddy这类轻量级Web服务器即可。

  1. 安装FFmpeg(用于视频转码和缩略图提取)。
  2. 将你的电影源文件(如 movie.mp4 )使用FFmpeg转码为多码率的HLS格式:
    ffmpeg -i movie.mp4 -c:v libx264 -c:a aac -f hls -hls_time 4 -hls_playlist_type vod -hls_segment_filename "v%v/segment_%03d.ts" -master_pl_name "master.m3u8" -var_stream_map "v:0,a:0 v:1,a:1" -vcodec libx264 -acodec aac -s 1280x720 -b:v 2500k -b:a 128k v_720.m3u8 -vcodec libx264 -acodec aac -s 854x480 -b:v 1000k -b:a 96k v_480.m3u8
    
  3. 运行上一步的缩略图容器生成脚本,得到 containers/ 目录下的所有容器图片。
  4. 将生成的 v_720.m3u8 , v_480.m3u8 segment_*.ts 文件所在的文件夹,以及 containers/ 文件夹,都放到Web服务器(如Nginx)的根目录下。确保服务器正确配置了 .m3u8 .ts 文件的MIME类型。

第二步:准备客户端动作识别模型

  1. 数据准备 :从UCF-101数据集中,为你关心的动作类别(如 HorseRiding , SoccerPenalty )抽取训练图片。每个视频抽取多帧,并打上标签。
  2. 模型训练 :使用迁移学习。以一个预训练的MobileNetV2(ImageNet权重)为基础,移除其顶部分类层,添加新的适用于你动作类别的全连接层。在你的数据集上进行微调。
    # 简化示例 - 使用TensorFlow/Keras
    base_model = tf.keras.applications.MobileNetV2(input_shape=(90, 160, 3), include_top=False, weights='imagenet')
    base_model.trainable = False # 先冻结基础模型权重
    model = tf.keras.Sequential([
        base_model,
        tf.keras.layers.GlobalAveragePooling2D(),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(num_actions, activation='softmax') # num_actions是你的动作类别数
    ])
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    model.fit(train_dataset, epochs=10, validation_data=val_dataset)
    
  3. 模型转换 :将训练好的Keras模型转换为TensorFlow.js格式,以便在浏览器中运行。
    tensorflowjs_converter --input_format keras path/to/your_model.h5 path/to/tfjs_model_dir
    

4.2 客户端应用核心逻辑实现

客户端是一个单页Web应用,核心是三个模块:HLS播放器、UI交互层、以及缩略图分析引擎。

1. 初始化与资源加载

// 1. 初始化HLS播放器
const videoElement = document.getElementById('video');
const hls = new Hls(); // 使用hls.js库
hls.loadSource('http://your-server/master.m3u8');
hls.attachMedia(videoElement);

// 2. 加载TensorFlow.js模型
let model;
async function loadModel() {
    model = await tf.loadGraphModel('path/to/tfjs_model_dir/model.json');
}
loadModel();

// 3. 加载并解析缩略图容器元数据
// 假设有一个manifest.json文件,记录了电影总时长和对应的容器文件列表
const manifest = await fetch('containers/manifest.json').then(r => r.json());

2. 用户交互与动作选择 在UI上提供一组按钮,代表可识别的动作(如“骑马”、“射门”)。用户点击后,触发分析流程。

3. 缩略图分析引擎(核心)

async function analyzeThumbnailsForAction(selectedAction, manifest) {
    const detectedTimestamps = [];
    const actionIndex = ACTION_LABELS.indexOf(selectedAction); // 获取动作在模型输出中的索引

    for (const containerInfo of manifest.containers) {
        // 加载一个缩略图容器图片
        const containerImg = await loadImage(`containers/${containerInfo.filename}`);
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');

        // 遍历容器中的25个缩略图位置
        for (let row = 0; row < 5; row++) {
            for (let col = 0; col < 5; col++) {
                const thumbIndex = row * 5 + col;
                const globalSecond = containerInfo.startSecond + thumbIndex;

                // 从大图中裁剪出单个缩略图
                ctx.drawImage(containerImg, col * 160, row * 90, 160, 90, 0, 0, 160, 90);
                const imageData = ctx.getImageData(0, 0, 160, 90);

                // 预处理图像数据,匹配模型输入要求
                const tensor = tf.browser.fromPixels(imageData)
                    .resizeNearestNeighbor([90, 160]) // 模型输入尺寸
                    .toFloat()
                    .div(255.0)
                    .expandDims(0);

                // 模型推理
                const predictions = await model.predict(tensor);
                const score = predictions.dataSync()[actionIndex];
                tensor.dispose(); // 及时释放Tensor内存,避免泄漏

                // 如果置信度超过阈值,记录时间戳
                if (score > DETECTION_THRESHOLD) {
                    detectedTimestamps.push({
                        second: globalSecond,
                        score: score
                    });
                }
            }
        }
    }

    // 对检测到的时间点按置信度排序,并应用非极大值抑制(NMS)避免时间点过于密集
    return postProcessTimestamps(detectedTimestamps);
}

4. 动态生成并播放个性化预告片

async function generateAndPlayTrailer(timestamps) {
    // 1. 将时间戳转换为HLS片段请求列表
    // 需要根据master.m3u8和媒体播放列表,计算每个时间点对应的片段序号和字节范围
    const segmentRequests = timestamps.map(ts => calculateSegmentRequest(ts.second));

    // 2. 动态构建一个虚拟的HLS播放列表
    const virtualPlaylist = `#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
${segmentRequests.map(req => `#EXTINF:4.0,\n${req.url}`).join('\n')}
#EXT-X-ENDLIST`;

    // 3. 创建一个Blob URL指向这个虚拟播放列表
    const blob = new Blob([virtualPlaylist], {type: 'application/vnd.apple.mpegurl'});
    const virtualPlaylistUrl = URL.createObjectURL(blob);

    // 4. 让HLS播放器加载这个虚拟列表
    hls.loadSource(virtualPlaylistUrl);
    hls.attachMedia(videoElement);
    videoElement.play();
}

4.3 性能优化与体验打磨

在基础流程跑通后,以下优化能极大提升实用性和用户体验:

  • 并行下载与分析 :不要等所有缩略图容器下载完再开始分析。可以实现一个流水线:下载第1个容器 -> 开始分析 -> 同时下载第2个容器 -> 分析第1个容器完成,开始分析第2个 -> 以此类推。这能显著减少用户等待时间。
  • 渐进式预览 :在分析过程中,一旦识别出几个高置信度的时间点,就可以立即开始预加载对应的视频片段,并尝试播放一个“预览版”短片。随着分析继续,不断在后台更新和延长这个预告片。给用户一种“即时响应”的感觉。
  • 模型量化与加速 :将训练好的模型进行 量化 (如从FP32转换为INT8),可以大幅减少模型体积和提升推理速度,几乎不影响精度。TensorFlow Lite和TensorFlow.js都支持此操作。
  • 本地存储偏好 :将用户选择过的动作偏好存储在本地(如 localStorage )。下次用户打开同一部电影时,可以直接加载之前分析好的时间戳列表,实现“秒开”个性化预告。

5. 常见问题、挑战与实战避坑指南

在实际开发和测试这套框架的过程中,我遇到了不少预料之外的问题。这里分享一些典型的挑战和解决思路,希望能帮你绕过这些坑。

5.1 动作识别的准确性与“语义鸿沟”

问题 :基于单帧缩略图的动作识别,其准确率天然低于基于视频片段的识别。一个“骑马”的动作,在静态帧中可能只是一个模糊的人影或马背的一部分,模型很容易误判或漏判。

解决思路与技巧

  1. 数据增强与针对性训练 :在准备训练数据时,不能只从视频中随机采样。应重点采集能代表动作 关键姿态 的帧(如投球手臂挥到最高点、射门脚接触球的瞬间)。同时,对训练图片进行针对性的增强,如模拟缩略图的低分辨率、轻微的模糊和压缩噪声,让模型更适应真实场景。
  2. 后处理与上下文平滑 :不要完全依赖单帧的置信度。利用动作在时间上的连续性进行平滑处理。例如,如果连续3-5秒内有多帧被识别为同一动作(即使个别帧置信度不高),那么这段区间很可能就是该动作发生的段落。可以采用滑动窗口或条件随机场(CRF)等简单的时间模型来提升鲁棒性。
  3. 多模态信息辅助(进阶) :如果条件允许,可以结合音频或字幕(封闭字幕)信息。例如,识别到“枪声”的音频事件或“马嘶鸣”的字幕,可以极大地辅助确认“西部片枪战”或“骑马”场景。这些元数据同样可以轻量化地预先提取并与时间轴对齐。

5.2 网络与客户端资源的动态平衡

问题 :在弱网环境下,同时下载视频流和大量缩略图容器可能造成拥塞。在低端设备上,同时进行视频解码和神经网络推理可能导致卡顿。

策略

  • 自适应缩略图质量 :服务器可以准备不同清晰度的缩略图容器(如80x45, 160x90, 320x180)。客户端可以根据当前网络状况和设备性能,动态请求不同质量的版本。分析低质量版本,虽然准确率可能略有下降,但能保证流程的可用性。
  • 计算任务调度 :将耗时的模型推理任务放在 requestIdleCallback (浏览器)或低优先级后台线程中执行,确保视频播放的主线程永远流畅。可以设置一个分析进度条,让用户感知后台工作,同时不影响前台观看(如果用户选择先看官方预告片)。
  • 分段懒加载分析 :不必一次性分析整部电影。可以先分析前10%的缩略图,快速生成一个短预告。如果用户感兴趣,再在后台继续分析后面的部分,并动态更新预告片内容。

5.3 HLS片段精准裁剪与播放兼容性

问题 :HLS协议设计用于连续播放,直接请求不连续的片段可能会导致播放器行为异常(如跳闪、音画不同步)。精确到帧级别的裁剪(只取片段中的某一小段)更是一个挑战。

实战方案

  1. 保守策略——整段请求 :最简单可靠的方法是,只要识别的时间点落在某个片段内,就请求整个片段。这样能100%保证播放兼容性。代价是预告片中会包含一些无关内容,导致预告片略显拖沓。可以通过在客户端进行简单的 片段内裁剪 来缓解:播放器加载完整片段后,使用 video.currentTime 跳转到识别时间点附近开始播放,并在到达下一个识别点或片段末尾前停止/跳转。这需要更精细的播放器控制逻辑。
  2. 进阶策略——服务端辅助裁剪 :可以与服务器约定一个简单的API。客户端将识别出的精确时间范围(如 {start: 305.2, end: 308.5} )发送给服务器,服务器端利用FFmpeg实时将原始视频的对应部分裁剪并封装成一个新的、更短的 .ts 片段返回给客户端。这实现了最精准的预览,但增加了服务器端的计算负担,失去了部分“客户端驱动”的纯粹性,更适合对预览精度要求极高的场景。

5.4 系统扩展性与多类型内容适配

问题 :最初的实验只针对“西部片”和“体育片”中的几种特定动作。如何扩展到爱情片、科幻片或纪录片?不同类型的电影,其“精彩瞬间”的定义截然不同。

扩展思路

  • 可插拔的兴趣模型 :系统不应绑定于单一的动作识别模型。可以设计一个插件化的架构。客户端根据电影的类型(从元数据获取),动态加载对应的“兴趣检测器”模型。对于爱情片,模型可以是识别“拥抱”、“亲吻”、“对视”等场景;对于科幻片,则识别“爆炸”、“激光”、“太空船”等。模型本身可以很小,只专注于特定类型的几个标签。
  • 结合通用语义特征 :除了专用的小模型,可以引入一个通用的场景识别或物体检测模型(同样需轻量化)。用户甚至可以用自然语言输入兴趣点,如“我想看有美丽风景的片段”或“找出所有有狗狗出现的镜头”。这需要将自然语言查询与视觉特征的语义嵌入进行匹配,实现更灵活的个性化。

经过这一系列的拆解、实现和优化,一个真正在客户端运行、保护隐私、且能快速生成个性化预告片的系统就从论文走进了现实。它或许没有专业剪辑师制作的预告片那样充满艺术性和戏剧张力,但它代表了一种方向:将个性化的权力和安全归还给用户,利用边缘计算的智慧,在资源受限的环境中创造全新的体验。这种以轻量级视觉索引为核心,在边缘进行智能筛选的思路,其实可以延伸到很多领域,比如生成个人相册的智能精选集、从长讲座视频中提取你感兴趣的知识点片段等等。技术的魅力,往往就在于这种用一个巧妙的支点,撬动传统难题的瞬间。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐