パートナーシップ

TwelveLabsとPixeltableを使用したクロスモーダル動画検索の構築

ジェームズ・リー

Twelve LabsのMarengo 3.0埋め込み(embeddings)とPixeltableの宣言型データインフラストラクチャを使用することで、開発者はクロスモーダルなビデオ検索システムを構築できます。これにより、自動化された埋め込み計算と増分更新機能を用いて、同一の統合されたセマンティックインデックスに対してテキスト、画像、音声、およびビデオによるクエリを実行可能になります。

Twelve LabsのMarengo 3.0埋め込み(embeddings)とPixeltableの宣言型データインフラストラクチャを使用することで、開発者はクロスモーダルなビデオ検索システムを構築できます。これにより、自動化された埋め込み計算と増分更新機能を用いて、同一の統合されたセマンティックインデックスに対してテキスト、画像、音声、およびビデオによるクエリを実行可能になります。

この記事の内容

No headings found on page

ニュースレターに登録する

ニュースレターに登録する

ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします

ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします

AIを活用してビデオを検索、分析、探索します。

2026/02/04

5分

記事へのリンクをコピー

この統合の実現にあたり、私とコラボレーションしてくれたPixeltableチーム(Alison HillPierre BrunelleMarcel Kornacker、およびAaron Siegel)に深く感謝いたします!


はじめに

インテリジェントな動画アプリケーションの構築には、根本的な課題があります。それは、動画には視覚コンテンツ、音声、テキストといった複数のモダリティが含まれており、従来の検索システムではこれらをシームレスにクエリするのが難しいという点です。開発者は通常、各モダリティ用の個別のモデルや、複雑な橋渡しロジック、そしてクロスモーダル検索を実現するための多大なエンジニアリングの労力を必要とします。

TwelveLabsのマルチモーダル埋め込み(embeddings)は、テキスト、画像、音声、動画を統一されたセマンティック空間に投影することで、この課題を解決します。これにより、あらゆるモダリティを使用して動画ライブラリを検索できるようになります。テキスト説明を使ってクリップを見つけたり("スピーチをしている人")、参照画像に視覚的に似た動画を特定したり、一致する音声特性のコンテンツを発見したり、類似する動画セグメントを特定したりすることが、すべて同じ埋め込みモデルを使用して行えます。

(※日本語翻訳用の便宜上の段落調整として、このまま次の段落へ進みます)

このチュートリアルでは、TwelveLabsのMarengo 3.0モデルと、マルチモーダルAIのためのPixeltableの宣言型データインフラストラクチャを組み合わせて、完全なクロスモーダル動画検索システムを構築します。Pixeltableは、埋め込み計算、インデックス作成、および増分更新の複雑さを自動的に処理するため、インフラストラクチャの管理に追われることなく、機能の構築に集中できます。最後まで進めると、最小限のコードで真のマルチモーダル動画理解を実証する、実際に動作するシステムが完成します。


前提条件とセットアップ

クロスモーダル検索システムを構築する前に、Python 3.8以降がインストールされていることを確認してください。また、TwelveLabsのAPIキーが必要です。APIキーは playground.twelvelabs.io でサインアップすることで取得できます。

まず、必要なパッケージをインストールします:

pip install -qU

次に、TwelveLabsのAPIキーを安全に設定します。環境変数として設定するか、対話的に入力することができます:

import os
import getpass

if 'TWELVELABS_API_KEY' not in os.environ:
    os.environ['TWELVELABS_API_KEY'] = getpass.getpass('Enter your Twelve Labs API key: ')

Pixeltableを初期化し、このプロジェクト専用のディレクトリを作成します:

import pixeltable as pxt
from pixeltable.functions.twelvelabs import embed

# Create a fresh directory for our video search system
pxt.drop_dir('video_search', force=True)
pxt.create_dir('video_search')

Pixeltableは、このディレクトリ内でのデータの永続化、バージョン管理、およびメタデータの追跡を自動的に処理します。

重要: Twelve Labsは、最適な埋め込み品質を確保するために、音声および動画コンテンツの長さを4秒以上にすることを要求しています。動画コンテンツを用意する際は、この制約に留意してください。


コアコンセプト:マルチモーダル埋め込み

従来の動画検索では、視覚コンテンツ用、音声用、テキスト用といったモダリティごとの個別モデルと、それらを橋渡しする複雑なロジックが必要でした。TwelveLabsのMarengoモデルは根本的に異なるアプローチを採用しており、すべてのモダリティが共存する統一されたセマンティック空間を作成します。

この共有空間では、誰かが話している動画クリップ、その発言の書き起こしテキスト、動画の静止フレーム、そしてテキストによる説明がすべて近いポイントにマッピングされます。これにより、任意のモダリティでクエリを行い、任意のモダリティから関連コンテンツを取得する、真のクロスモーダル検索が可能になります。

以下は、これから構築するクロスモーダル検索機能の概要です:

クエリタイプ

ユースケース

テキスト → 動画

「スピーチをしている人」に一致するクリップを検索

画像 → 動画

参照写真に視覚的に類似した動画を特定

音声 → 動画

類似した音声特性を持つコンテンツを発見

動画 → 動画

類似したクリップや別テイクを特定

この統一された埋め込み空間こそが、TwelveLabsとPixeltableの統合を非常に強力にしている要素です。一度構築すれば、すべてのモダリティにわたるシームレスな検索が可能になります。


動画検索システムの構築

PixeltableとTwelveLabsを使用して検索可能な動画インデックスを作成するには、いくつかの宣言的なステップを実行するだけです。まず、動画を保存するテーブルを定義します:

from pixeltable.functions.video import splitter

# Create a table for videos
videos = pxt.create_table('video_search.videos', {'video': pxt.Video})

# Insert a sample video
video_url = 'https://github.com/pixeltable/pixeltable/raw/main/docs/resources/The-Pursuit-of-Happiness.mp4'
videos.insert([{'video': video_url}])

次に、動画を検索可能なチャンク(塊)に分割するビューを作成します。ここでPixeltableのイテレータ機能が威力を発揮します:

splitter イテレータは、TwelveLabsの4秒以上という最小制限を下回らないように配慮した上で、各動画を5秒のセグメントに自動分割します。このビューの各行が、1つの動画セグメントを表します。

ここで、最も重要なステップである埋め込みインデックスの追加を行います:

# Add embedding index for cross-modal search
video_chunks.add_embedding_index(
    'video_segment',
    embedding=embed.using(model_name='marengo3.0')
)

この1行によって、強力な自動化が始まります。Pixeltableはすべての動画セグメントに対してTwelveLabsの埋め込みを計算し、インデックスを増分的に維持します。新しい動画を追加すると、手動での調整を必要とせずに埋め込みが自動的に計算されます。

この宣言的アプローチの利点は、データをどのように処理するかではなく、何を計算するか(動画セグメントの埋め込み)を指定できる点にあります。Pixeltableが裏でバッチ処理、エラー回復、キャッシングを処理します。


クロスモーダル検索の仕組みと例

動画インデックスが構築されたら、任意のモダリティを使用して検索を行うことができます。理解すべき重要なAPIは、video_segment カラムに対して呼び出して再利用可能な類似度式を生成する similarity() メソッドです。


テキストから動画を検索する(Text-to-Video)

はじめに、テキストクエリに対する類似度式を定義します:

# Define similarity to a text query
sim = video_chunks.video_segment.similarity(string='person giving a speech')

# Get the top 3 matching segments
results = video_chunks.order_by(sim, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim
)

results.collect()

ここで sim は「各セグメントと入力テキスト文字列との類似度」を表す式であり、order_byselect、または追加のフィルタの中で使用できます。


画像から動画を検索する(Image-to-Video)

画像クエリについても同様のパターンを使用します:

# Load a reference image
reference_image = pxt.Image('path/to/reference_image.jpg')

# Define similarity to the image
sim_image = video_chunks.video_segment.similarity(image=reference_image)

# Top 3 visually similar segments
results = video_chunks.order_by(sim_image, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_image
)

results.collect()

これにより、視覚的な内容が参照画像に最も近い動画セグメントを見つけ出すことができます。


音声から動画を検索する(Audio-to-Video)

音声クリップを使用して検索することもできます:

# Load a reference audio sample
reference_audio = pxt.Audio('path/to/reference_audio.mp3')

# Define similarity to the audio
sim_audio = video_chunks.video_segment.similarity(audio=reference_audio)

# Top 3 segments with similar audio characteristics
results = video_chunks.order_by(sim_audio, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_audio
)

results.collect()

これは、BGM、話し方、またはその他の音響パターンのマッチングに役立ちます。


動画から動画を検索する(Video-to-Video)

最後に、動画(またはセグメント)自体をクエリとして使用して、類似したクリップを特定します:

# Use an existing segment as the query
query_segment = (
    video_chunks
        .select(video_chunks.video_segment)
        .limit(1)
        .collect()[0]['video_segment']
)

# Define similarity to the query segment
sim_video = video_chunks.video_segment.similarity(video=query_segment)

# Top 5 similar segments across the library
results = video_chunks.order_by(sim_video, asc=False).limit(5).select(
    video_chunks.video_segment,
    score=sim_video
)

results.collect()

これにより、コンテンツ推薦システム、重複の検出、または類似したシーンの別テイクの発見などが可能になります。

4つのケースすべてで同じパターンに従っています。video_segment カラムに対して similarity() 式を定義し、その式を order_byselect で再利用して、テキスト、画像、音声、またはビデオのクエリに対して最適なマッチを取得します。


動画にとどまらない:マルチモーダルデータタイプ

Twelve Labsの埋め込みは動画にとどまらず、真のマルチモーダルアプリケーションの構築を可能にします。同じMarengoモデルを使用して、テキスト文書、単体の画像、音声ファイルを埋め込むことができ、異種混合のデータタイプにわたる検索が可能になります。

複数のモダリティを持つ製品カタログテーブルを作成してみましょう:

# Create a product catalog with text and images
products = pxt.create_table(
    'video_search.products',
    {
        'title': pxt.String,
        'description': pxt.String,
        'thumbnail': pxt.Image
    }
)

# Add computed column combining title and description
products.add_computed_column(
		text_content=products.title + '. ' + products.description,
		if_exists='replace'
)

# Add embedding indices for both text and images
products.add_embedding_index(
    'text_content',
    embedding=embed.using(model_name='marengo3.0')
)

products.add_embedding_index(
    'thumbnail',
    embedding=embed.using(model_name='marengo3.0')
)

続いて、クロスモーダルなカタログ検索を実行します:

# Search products using text
text_results = products.select(
    products.title,
    products.thumbnail,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.text_content.sim('outdoor hiking gear') > 0.6
).limit(5)

# Search products using an image
query_image = pxt.Image('path/to/query.jpg')
image_results = products.select(
    products.title,
    products.description,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.thumbnail.sim(query_image) > 0.7
).limit(5)

動画クリップを使用して製品カタログを検索したり、音声サンプルに関連する製品を見つけたりすることも可能です。この統一されたアプローチにより、テキストドキュメント、画像、音声ファイル、動画、およびそれらの任意の組み合わせなど、アプリケーション全体にわたる検索を単一の埋め込みモデルで動作させることができます。

同じパターンは他のユースケースにも適用されます。スクリーンショットを使ってドキュメントを検索する、テキストクエリに一致する音声クリップを見つける、動画フレームに類似した画像を特定する、といったことが可能です。Twelve Labsのマルチモーダル埋め込みは、データタイプ間の従来の境界を取り除きます。


パフォーマンスとベストプラクティス

Pixeltableは埋め込みの計算を自動的に最適化しますが、これらのベストプラクティスに従うことで、本番環境での最適なパフォーマンスを確保できます。

バッチ操作: 動画は1件ずつではなく、一度に複数挿入します。Pixeltableはバッチ処理により、より効率的に埋め込みを処理します:

# Efficient: batch insert
videos.insert([
    {'video': 'url1.mp4'},
    {'video': 'url2.mp4'},
    {'video': 'url3.mp4'}
])

類似度しきい値: 適合率と再現率の要件に基づいて、類似性のしきい値を調整してください。しきい値を高く設定すると(0.7〜0.9)より関連性の高い少数の結果が返り、低く設定すると(0.4〜0.6)より広い範囲の結果が得られます。お使いのコンテンツでテストし、最適な設定を見つけてください。

増分アップデート: Pixeltableの計算列は、新しいデータを追加すると自動的に更新されます。埋め込みインデックスは手動で再処理することなく最新の状態に保たれるため、いつでも新しい動画を挿入でき、直ちに検索可能になります。

キャッシュ: Pixeltableは埋め込みインデックスを管理します。データが一度インデックス化されれば、元データに変更がない限り、類似度検索に追加のAPI呼び出しは必要ありません。

エラーハンドリング: Pixeltableは、失敗した埋め込みの計算を自動的に再試行します(プロバイダーごとのレート制限を設定できるようにするには、構成の構成詳細を参照してください)。さらに、大規模なバッチ処理中にレート制限を回避するために、TwelveLabs APIのクォータを監視してください。

これらの手法を取り入れることで、エンドユーザーに対する低遅延を維持しながら、効率的にスケールする本番対応の動画検索システムを構築できます。


その他のリソース

この統合の実現にあたり、私とコラボレーションしてくれたPixeltableチーム(Alison HillPierre BrunelleMarcel Kornacker、およびAaron Siegel)に深く感謝いたします!


はじめに

インテリジェントな動画アプリケーションの構築には、根本的な課題があります。それは、動画には視覚コンテンツ、音声、テキストといった複数のモダリティが含まれており、従来の検索システムではこれらをシームレスにクエリするのが難しいという点です。開発者は通常、各モダリティ用の個別のモデルや、複雑な橋渡しロジック、そしてクロスモーダル検索を実現するための多大なエンジニアリングの労力を必要とします。

TwelveLabsのマルチモーダル埋め込み(embeddings)は、テキスト、画像、音声、動画を統一されたセマンティック空間に投影することで、この課題を解決します。これにより、あらゆるモダリティを使用して動画ライブラリを検索できるようになります。テキスト説明を使ってクリップを見つけたり("スピーチをしている人")、参照画像に視覚的に似た動画を特定したり、一致する音声特性のコンテンツを発見したり、類似する動画セグメントを特定したりすることが、すべて同じ埋め込みモデルを使用して行えます。

(※日本語翻訳用の便宜上の段落調整として、このまま次の段落へ進みます)

このチュートリアルでは、TwelveLabsのMarengo 3.0モデルと、マルチモーダルAIのためのPixeltableの宣言型データインフラストラクチャを組み合わせて、完全なクロスモーダル動画検索システムを構築します。Pixeltableは、埋め込み計算、インデックス作成、および増分更新の複雑さを自動的に処理するため、インフラストラクチャの管理に追われることなく、機能の構築に集中できます。最後まで進めると、最小限のコードで真のマルチモーダル動画理解を実証する、実際に動作するシステムが完成します。


前提条件とセットアップ

クロスモーダル検索システムを構築する前に、Python 3.8以降がインストールされていることを確認してください。また、TwelveLabsのAPIキーが必要です。APIキーは playground.twelvelabs.io でサインアップすることで取得できます。

まず、必要なパッケージをインストールします:

pip install -qU

次に、TwelveLabsのAPIキーを安全に設定します。環境変数として設定するか、対話的に入力することができます:

import os
import getpass

if 'TWELVELABS_API_KEY' not in os.environ:
    os.environ['TWELVELABS_API_KEY'] = getpass.getpass('Enter your Twelve Labs API key: ')

Pixeltableを初期化し、このプロジェクト専用のディレクトリを作成します:

import pixeltable as pxt
from pixeltable.functions.twelvelabs import embed

# Create a fresh directory for our video search system
pxt.drop_dir('video_search', force=True)
pxt.create_dir('video_search')

Pixeltableは、このディレクトリ内でのデータの永続化、バージョン管理、およびメタデータの追跡を自動的に処理します。

重要: Twelve Labsは、最適な埋め込み品質を確保するために、音声および動画コンテンツの長さを4秒以上にすることを要求しています。動画コンテンツを用意する際は、この制約に留意してください。


コアコンセプト:マルチモーダル埋め込み

従来の動画検索では、視覚コンテンツ用、音声用、テキスト用といったモダリティごとの個別モデルと、それらを橋渡しする複雑なロジックが必要でした。TwelveLabsのMarengoモデルは根本的に異なるアプローチを採用しており、すべてのモダリティが共存する統一されたセマンティック空間を作成します。

この共有空間では、誰かが話している動画クリップ、その発言の書き起こしテキスト、動画の静止フレーム、そしてテキストによる説明がすべて近いポイントにマッピングされます。これにより、任意のモダリティでクエリを行い、任意のモダリティから関連コンテンツを取得する、真のクロスモーダル検索が可能になります。

以下は、これから構築するクロスモーダル検索機能の概要です:

クエリタイプ

ユースケース

テキスト → 動画

「スピーチをしている人」に一致するクリップを検索

画像 → 動画

参照写真に視覚的に類似した動画を特定

音声 → 動画

類似した音声特性を持つコンテンツを発見

動画 → 動画

類似したクリップや別テイクを特定

この統一された埋め込み空間こそが、TwelveLabsとPixeltableの統合を非常に強力にしている要素です。一度構築すれば、すべてのモダリティにわたるシームレスな検索が可能になります。


動画検索システムの構築

PixeltableとTwelveLabsを使用して検索可能な動画インデックスを作成するには、いくつかの宣言的なステップを実行するだけです。まず、動画を保存するテーブルを定義します:

from pixeltable.functions.video import splitter

# Create a table for videos
videos = pxt.create_table('video_search.videos', {'video': pxt.Video})

# Insert a sample video
video_url = 'https://github.com/pixeltable/pixeltable/raw/main/docs/resources/The-Pursuit-of-Happiness.mp4'
videos.insert([{'video': video_url}])

次に、動画を検索可能なチャンク(塊)に分割するビューを作成します。ここでPixeltableのイテレータ機能が威力を発揮します:

splitter イテレータは、TwelveLabsの4秒以上という最小制限を下回らないように配慮した上で、各動画を5秒のセグメントに自動分割します。このビューの各行が、1つの動画セグメントを表します。

ここで、最も重要なステップである埋め込みインデックスの追加を行います:

# Add embedding index for cross-modal search
video_chunks.add_embedding_index(
    'video_segment',
    embedding=embed.using(model_name='marengo3.0')
)

この1行によって、強力な自動化が始まります。Pixeltableはすべての動画セグメントに対してTwelveLabsの埋め込みを計算し、インデックスを増分的に維持します。新しい動画を追加すると、手動での調整を必要とせずに埋め込みが自動的に計算されます。

この宣言的アプローチの利点は、データをどのように処理するかではなく、何を計算するか(動画セグメントの埋め込み)を指定できる点にあります。Pixeltableが裏でバッチ処理、エラー回復、キャッシングを処理します。


クロスモーダル検索の仕組みと例

動画インデックスが構築されたら、任意のモダリティを使用して検索を行うことができます。理解すべき重要なAPIは、video_segment カラムに対して呼び出して再利用可能な類似度式を生成する similarity() メソッドです。


テキストから動画を検索する(Text-to-Video)

はじめに、テキストクエリに対する類似度式を定義します:

# Define similarity to a text query
sim = video_chunks.video_segment.similarity(string='person giving a speech')

# Get the top 3 matching segments
results = video_chunks.order_by(sim, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim
)

results.collect()

ここで sim は「各セグメントと入力テキスト文字列との類似度」を表す式であり、order_byselect、または追加のフィルタの中で使用できます。


画像から動画を検索する(Image-to-Video)

画像クエリについても同様のパターンを使用します:

# Load a reference image
reference_image = pxt.Image('path/to/reference_image.jpg')

# Define similarity to the image
sim_image = video_chunks.video_segment.similarity(image=reference_image)

# Top 3 visually similar segments
results = video_chunks.order_by(sim_image, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_image
)

results.collect()

これにより、視覚的な内容が参照画像に最も近い動画セグメントを見つけ出すことができます。


音声から動画を検索する(Audio-to-Video)

音声クリップを使用して検索することもできます:

# Load a reference audio sample
reference_audio = pxt.Audio('path/to/reference_audio.mp3')

# Define similarity to the audio
sim_audio = video_chunks.video_segment.similarity(audio=reference_audio)

# Top 3 segments with similar audio characteristics
results = video_chunks.order_by(sim_audio, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_audio
)

results.collect()

これは、BGM、話し方、またはその他の音響パターンのマッチングに役立ちます。


動画から動画を検索する(Video-to-Video)

最後に、動画(またはセグメント)自体をクエリとして使用して、類似したクリップを特定します:

# Use an existing segment as the query
query_segment = (
    video_chunks
        .select(video_chunks.video_segment)
        .limit(1)
        .collect()[0]['video_segment']
)

# Define similarity to the query segment
sim_video = video_chunks.video_segment.similarity(video=query_segment)

# Top 5 similar segments across the library
results = video_chunks.order_by(sim_video, asc=False).limit(5).select(
    video_chunks.video_segment,
    score=sim_video
)

results.collect()

これにより、コンテンツ推薦システム、重複の検出、または類似したシーンの別テイクの発見などが可能になります。

4つのケースすべてで同じパターンに従っています。video_segment カラムに対して similarity() 式を定義し、その式を order_byselect で再利用して、テキスト、画像、音声、またはビデオのクエリに対して最適なマッチを取得します。


動画にとどまらない:マルチモーダルデータタイプ

Twelve Labsの埋め込みは動画にとどまらず、真のマルチモーダルアプリケーションの構築を可能にします。同じMarengoモデルを使用して、テキスト文書、単体の画像、音声ファイルを埋め込むことができ、異種混合のデータタイプにわたる検索が可能になります。

複数のモダリティを持つ製品カタログテーブルを作成してみましょう:

# Create a product catalog with text and images
products = pxt.create_table(
    'video_search.products',
    {
        'title': pxt.String,
        'description': pxt.String,
        'thumbnail': pxt.Image
    }
)

# Add computed column combining title and description
products.add_computed_column(
		text_content=products.title + '. ' + products.description,
		if_exists='replace'
)

# Add embedding indices for both text and images
products.add_embedding_index(
    'text_content',
    embedding=embed.using(model_name='marengo3.0')
)

products.add_embedding_index(
    'thumbnail',
    embedding=embed.using(model_name='marengo3.0')
)

続いて、クロスモーダルなカタログ検索を実行します:

# Search products using text
text_results = products.select(
    products.title,
    products.thumbnail,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.text_content.sim('outdoor hiking gear') > 0.6
).limit(5)

# Search products using an image
query_image = pxt.Image('path/to/query.jpg')
image_results = products.select(
    products.title,
    products.description,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.thumbnail.sim(query_image) > 0.7
).limit(5)

動画クリップを使用して製品カタログを検索したり、音声サンプルに関連する製品を見つけたりすることも可能です。この統一されたアプローチにより、テキストドキュメント、画像、音声ファイル、動画、およびそれらの任意の組み合わせなど、アプリケーション全体にわたる検索を単一の埋め込みモデルで動作させることができます。

同じパターンは他のユースケースにも適用されます。スクリーンショットを使ってドキュメントを検索する、テキストクエリに一致する音声クリップを見つける、動画フレームに類似した画像を特定する、といったことが可能です。Twelve Labsのマルチモーダル埋め込みは、データタイプ間の従来の境界を取り除きます。


パフォーマンスとベストプラクティス

Pixeltableは埋め込みの計算を自動的に最適化しますが、これらのベストプラクティスに従うことで、本番環境での最適なパフォーマンスを確保できます。

バッチ操作: 動画は1件ずつではなく、一度に複数挿入します。Pixeltableはバッチ処理により、より効率的に埋め込みを処理します:

# Efficient: batch insert
videos.insert([
    {'video': 'url1.mp4'},
    {'video': 'url2.mp4'},
    {'video': 'url3.mp4'}
])

類似度しきい値: 適合率と再現率の要件に基づいて、類似性のしきい値を調整してください。しきい値を高く設定すると(0.7〜0.9)より関連性の高い少数の結果が返り、低く設定すると(0.4〜0.6)より広い範囲の結果が得られます。お使いのコンテンツでテストし、最適な設定を見つけてください。

増分アップデート: Pixeltableの計算列は、新しいデータを追加すると自動的に更新されます。埋め込みインデックスは手動で再処理することなく最新の状態に保たれるため、いつでも新しい動画を挿入でき、直ちに検索可能になります。

キャッシュ: Pixeltableは埋め込みインデックスを管理します。データが一度インデックス化されれば、元データに変更がない限り、類似度検索に追加のAPI呼び出しは必要ありません。

エラーハンドリング: Pixeltableは、失敗した埋め込みの計算を自動的に再試行します(プロバイダーごとのレート制限を設定できるようにするには、構成の構成詳細を参照してください)。さらに、大規模なバッチ処理中にレート制限を回避するために、TwelveLabs APIのクォータを監視してください。

これらの手法を取り入れることで、エンドユーザーに対する低遅延を維持しながら、効率的にスケールする本番対応の動画検索システムを構築できます。


その他のリソース

この統合の実現にあたり、私とコラボレーションしてくれたPixeltableチーム(Alison HillPierre BrunelleMarcel Kornacker、およびAaron Siegel)に深く感謝いたします!


はじめに

インテリジェントな動画アプリケーションの構築には、根本的な課題があります。それは、動画には視覚コンテンツ、音声、テキストといった複数のモダリティが含まれており、従来の検索システムではこれらをシームレスにクエリするのが難しいという点です。開発者は通常、各モダリティ用の個別のモデルや、複雑な橋渡しロジック、そしてクロスモーダル検索を実現するための多大なエンジニアリングの労力を必要とします。

TwelveLabsのマルチモーダル埋め込み(embeddings)は、テキスト、画像、音声、動画を統一されたセマンティック空間に投影することで、この課題を解決します。これにより、あらゆるモダリティを使用して動画ライブラリを検索できるようになります。テキスト説明を使ってクリップを見つけたり("スピーチをしている人")、参照画像に視覚的に似た動画を特定したり、一致する音声特性のコンテンツを発見したり、類似する動画セグメントを特定したりすることが、すべて同じ埋め込みモデルを使用して行えます。

(※日本語翻訳用の便宜上の段落調整として、このまま次の段落へ進みます)

このチュートリアルでは、TwelveLabsのMarengo 3.0モデルと、マルチモーダルAIのためのPixeltableの宣言型データインフラストラクチャを組み合わせて、完全なクロスモーダル動画検索システムを構築します。Pixeltableは、埋め込み計算、インデックス作成、および増分更新の複雑さを自動的に処理するため、インフラストラクチャの管理に追われることなく、機能の構築に集中できます。最後まで進めると、最小限のコードで真のマルチモーダル動画理解を実証する、実際に動作するシステムが完成します。


前提条件とセットアップ

クロスモーダル検索システムを構築する前に、Python 3.8以降がインストールされていることを確認してください。また、TwelveLabsのAPIキーが必要です。APIキーは playground.twelvelabs.io でサインアップすることで取得できます。

まず、必要なパッケージをインストールします:

pip install -qU

次に、TwelveLabsのAPIキーを安全に設定します。環境変数として設定するか、対話的に入力することができます:

import os
import getpass

if 'TWELVELABS_API_KEY' not in os.environ:
    os.environ['TWELVELABS_API_KEY'] = getpass.getpass('Enter your Twelve Labs API key: ')

Pixeltableを初期化し、このプロジェクト専用のディレクトリを作成します:

import pixeltable as pxt
from pixeltable.functions.twelvelabs import embed

# Create a fresh directory for our video search system
pxt.drop_dir('video_search', force=True)
pxt.create_dir('video_search')

Pixeltableは、このディレクトリ内でのデータの永続化、バージョン管理、およびメタデータの追跡を自動的に処理します。

重要: Twelve Labsは、最適な埋め込み品質を確保するために、音声および動画コンテンツの長さを4秒以上にすることを要求しています。動画コンテンツを用意する際は、この制約に留意してください。


コアコンセプト:マルチモーダル埋め込み

従来の動画検索では、視覚コンテンツ用、音声用、テキスト用といったモダリティごとの個別モデルと、それらを橋渡しする複雑なロジックが必要でした。TwelveLabsのMarengoモデルは根本的に異なるアプローチを採用しており、すべてのモダリティが共存する統一されたセマンティック空間を作成します。

この共有空間では、誰かが話している動画クリップ、その発言の書き起こしテキスト、動画の静止フレーム、そしてテキストによる説明がすべて近いポイントにマッピングされます。これにより、任意のモダリティでクエリを行い、任意のモダリティから関連コンテンツを取得する、真のクロスモーダル検索が可能になります。

以下は、これから構築するクロスモーダル検索機能の概要です:

クエリタイプ

ユースケース

テキスト → 動画

「スピーチをしている人」に一致するクリップを検索

画像 → 動画

参照写真に視覚的に類似した動画を特定

音声 → 動画

類似した音声特性を持つコンテンツを発見

動画 → 動画

類似したクリップや別テイクを特定

この統一された埋め込み空間こそが、TwelveLabsとPixeltableの統合を非常に強力にしている要素です。一度構築すれば、すべてのモダリティにわたるシームレスな検索が可能になります。


動画検索システムの構築

PixeltableとTwelveLabsを使用して検索可能な動画インデックスを作成するには、いくつかの宣言的なステップを実行するだけです。まず、動画を保存するテーブルを定義します:

from pixeltable.functions.video import splitter

# Create a table for videos
videos = pxt.create_table('video_search.videos', {'video': pxt.Video})

# Insert a sample video
video_url = 'https://github.com/pixeltable/pixeltable/raw/main/docs/resources/The-Pursuit-of-Happiness.mp4'
videos.insert([{'video': video_url}])

次に、動画を検索可能なチャンク(塊)に分割するビューを作成します。ここでPixeltableのイテレータ機能が威力を発揮します:

splitter イテレータは、TwelveLabsの4秒以上という最小制限を下回らないように配慮した上で、各動画を5秒のセグメントに自動分割します。このビューの各行が、1つの動画セグメントを表します。

ここで、最も重要なステップである埋め込みインデックスの追加を行います:

# Add embedding index for cross-modal search
video_chunks.add_embedding_index(
    'video_segment',
    embedding=embed.using(model_name='marengo3.0')
)

この1行によって、強力な自動化が始まります。Pixeltableはすべての動画セグメントに対してTwelveLabsの埋め込みを計算し、インデックスを増分的に維持します。新しい動画を追加すると、手動での調整を必要とせずに埋め込みが自動的に計算されます。

この宣言的アプローチの利点は、データをどのように処理するかではなく、何を計算するか(動画セグメントの埋め込み)を指定できる点にあります。Pixeltableが裏でバッチ処理、エラー回復、キャッシングを処理します。


クロスモーダル検索の仕組みと例

動画インデックスが構築されたら、任意のモダリティを使用して検索を行うことができます。理解すべき重要なAPIは、video_segment カラムに対して呼び出して再利用可能な類似度式を生成する similarity() メソッドです。


テキストから動画を検索する(Text-to-Video)

はじめに、テキストクエリに対する類似度式を定義します:

# Define similarity to a text query
sim = video_chunks.video_segment.similarity(string='person giving a speech')

# Get the top 3 matching segments
results = video_chunks.order_by(sim, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim
)

results.collect()

ここで sim は「各セグメントと入力テキスト文字列との類似度」を表す式であり、order_byselect、または追加のフィルタの中で使用できます。


画像から動画を検索する(Image-to-Video)

画像クエリについても同様のパターンを使用します:

# Load a reference image
reference_image = pxt.Image('path/to/reference_image.jpg')

# Define similarity to the image
sim_image = video_chunks.video_segment.similarity(image=reference_image)

# Top 3 visually similar segments
results = video_chunks.order_by(sim_image, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_image
)

results.collect()

これにより、視覚的な内容が参照画像に最も近い動画セグメントを見つけ出すことができます。


音声から動画を検索する(Audio-to-Video)

音声クリップを使用して検索することもできます:

# Load a reference audio sample
reference_audio = pxt.Audio('path/to/reference_audio.mp3')

# Define similarity to the audio
sim_audio = video_chunks.video_segment.similarity(audio=reference_audio)

# Top 3 segments with similar audio characteristics
results = video_chunks.order_by(sim_audio, asc=False).limit(3).select(
    video_chunks.video_segment,
    score=sim_audio
)

results.collect()

これは、BGM、話し方、またはその他の音響パターンのマッチングに役立ちます。


動画から動画を検索する(Video-to-Video)

最後に、動画(またはセグメント)自体をクエリとして使用して、類似したクリップを特定します:

# Use an existing segment as the query
query_segment = (
    video_chunks
        .select(video_chunks.video_segment)
        .limit(1)
        .collect()[0]['video_segment']
)

# Define similarity to the query segment
sim_video = video_chunks.video_segment.similarity(video=query_segment)

# Top 5 similar segments across the library
results = video_chunks.order_by(sim_video, asc=False).limit(5).select(
    video_chunks.video_segment,
    score=sim_video
)

results.collect()

これにより、コンテンツ推薦システム、重複の検出、または類似したシーンの別テイクの発見などが可能になります。

4つのケースすべてで同じパターンに従っています。video_segment カラムに対して similarity() 式を定義し、その式を order_byselect で再利用して、テキスト、画像、音声、またはビデオのクエリに対して最適なマッチを取得します。


動画にとどまらない:マルチモーダルデータタイプ

Twelve Labsの埋め込みは動画にとどまらず、真のマルチモーダルアプリケーションの構築を可能にします。同じMarengoモデルを使用して、テキスト文書、単体の画像、音声ファイルを埋め込むことができ、異種混合のデータタイプにわたる検索が可能になります。

複数のモダリティを持つ製品カタログテーブルを作成してみましょう:

# Create a product catalog with text and images
products = pxt.create_table(
    'video_search.products',
    {
        'title': pxt.String,
        'description': pxt.String,
        'thumbnail': pxt.Image
    }
)

# Add computed column combining title and description
products.add_computed_column(
		text_content=products.title + '. ' + products.description,
		if_exists='replace'
)

# Add embedding indices for both text and images
products.add_embedding_index(
    'text_content',
    embedding=embed.using(model_name='marengo3.0')
)

products.add_embedding_index(
    'thumbnail',
    embedding=embed.using(model_name='marengo3.0')
)

続いて、クロスモーダルなカタログ検索を実行します:

# Search products using text
text_results = products.select(
    products.title,
    products.thumbnail,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.text_content.sim('outdoor hiking gear') > 0.6
).limit(5)

# Search products using an image
query_image = pxt.Image('path/to/query.jpg')
image_results = products.select(
    products.title,
    products.description,
    products.score
).order_by(
    products.score, asc=False
).where(
    products.thumbnail.sim(query_image) > 0.7
).limit(5)

動画クリップを使用して製品カタログを検索したり、音声サンプルに関連する製品を見つけたりすることも可能です。この統一されたアプローチにより、テキストドキュメント、画像、音声ファイル、動画、およびそれらの任意の組み合わせなど、アプリケーション全体にわたる検索を単一の埋め込みモデルで動作させることができます。

同じパターンは他のユースケースにも適用されます。スクリーンショットを使ってドキュメントを検索する、テキストクエリに一致する音声クリップを見つける、動画フレームに類似した画像を特定する、といったことが可能です。Twelve Labsのマルチモーダル埋め込みは、データタイプ間の従来の境界を取り除きます。


パフォーマンスとベストプラクティス

Pixeltableは埋め込みの計算を自動的に最適化しますが、これらのベストプラクティスに従うことで、本番環境での最適なパフォーマンスを確保できます。

バッチ操作: 動画は1件ずつではなく、一度に複数挿入します。Pixeltableはバッチ処理により、より効率的に埋め込みを処理します:

# Efficient: batch insert
videos.insert([
    {'video': 'url1.mp4'},
    {'video': 'url2.mp4'},
    {'video': 'url3.mp4'}
])

類似度しきい値: 適合率と再現率の要件に基づいて、類似性のしきい値を調整してください。しきい値を高く設定すると(0.7〜0.9)より関連性の高い少数の結果が返り、低く設定すると(0.4〜0.6)より広い範囲の結果が得られます。お使いのコンテンツでテストし、最適な設定を見つけてください。

増分アップデート: Pixeltableの計算列は、新しいデータを追加すると自動的に更新されます。埋め込みインデックスは手動で再処理することなく最新の状態に保たれるため、いつでも新しい動画を挿入でき、直ちに検索可能になります。

キャッシュ: Pixeltableは埋め込みインデックスを管理します。データが一度インデックス化されれば、元データに変更がない限り、類似度検索に追加のAPI呼び出しは必要ありません。

エラーハンドリング: Pixeltableは、失敗した埋め込みの計算を自動的に再試行します(プロバイダーごとのレート制限を設定できるようにするには、構成の構成詳細を参照してください)。さらに、大規模なバッチ処理中にレート制限を回避するために、TwelveLabs APIのクォータを監視してください。

これらの手法を取り入れることで、エンドユーザーに対する低遅延を維持しながら、効率的にスケールする本番対応の動画検索システムを構築できます。


その他のリソース