mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-18 14:53:05 +08:00
Add files present in zh-CN but missing from ja-JP: - commands: claw, context-budget, devfleet, docs, projects, prompt-optimize, rules-distill (7 files) - skills: regex-vs-llm-structured-text, remotion-video-creation, repo-scan, research-ops, returns-reverse-logistics, rules-distill, rust-patterns, rust-testing, skill-comply, skill-stocktake, social-graph-ranker, swift-actor-persistence, swift-concurrency-6-2, swift-protocol-di-testing, swiftui-patterns, team-builder, terminal-ops, token-budget-advisor, ui-demo, unified-notifications-ops, video-editing, videodb (+reference/*), visa-doc-translate, workspace-surface-audit, x-api (37 files) Result: ja-JP now has 517 files vs zh-CN 412 files. zh-CN parity: 0 missing files (complete parity achieved).
568 lines
17 KiB
Markdown
568 lines
17 KiB
Markdown
# RTStreamリファレンス
|
||
|
||
RTStream操作のコードレベルの詳細。ワークフローガイドは [rtstream.md](rtstream.md) を参照。
|
||
使用ガイダンスとフロー選択については、[../SKILL.md](../SKILL.md) から始めること。
|
||
|
||
[docs.videodb.io](https://docs.videodb.io/pages/ingest/live-streams/realtime-apis.md) に基づく。
|
||
|
||
***
|
||
|
||
## CollectionのRTStreamメソッド
|
||
|
||
`Collection` 上でRTStreamを管理するメソッド:
|
||
|
||
| メソッド | 戻り値 | 説明 |
|
||
|--------|---------|-------------|
|
||
| `coll.connect_rtstream(url, name, ...)` | `RTStream` | RTSP/RTMP URLから新しいRTStreamを作成する |
|
||
| `coll.get_rtstream(id)` | `RTStream` | IDで既存のRTStreamを取得する |
|
||
| `coll.list_rtstreams(limit, offset, status, name, ordering)` | `List[RTStream]` | コレクション内のすべてのRTStreamをリストする |
|
||
| `coll.search(query, namespace="rtstream")` | `RTStreamSearchResult` | すべてのRTStreamで検索する |
|
||
|
||
### RTStreamへの接続
|
||
|
||
```python
|
||
import videodb
|
||
|
||
conn = videodb.connect()
|
||
coll = conn.get_collection()
|
||
|
||
rtstream = coll.connect_rtstream(
|
||
url="rtmp://your-stream-server/live/stream-key",
|
||
name="My Live Stream",
|
||
media_types=["video"], # or ["audio", "video"]
|
||
sample_rate=30, # optional
|
||
store=True, # enable recording storage for export
|
||
enable_transcript=True, # optional
|
||
ws_connection_id=ws_id, # optional, for real-time events
|
||
)
|
||
```
|
||
|
||
### 既存のRTStreamを取得する
|
||
|
||
```python
|
||
rtstream = coll.get_rtstream("rts-xxx")
|
||
```
|
||
|
||
### RTStreamをリストする
|
||
|
||
```python
|
||
rtstreams = coll.list_rtstreams(
|
||
limit=10,
|
||
offset=0,
|
||
status="connected", # optional filter
|
||
name="meeting", # optional filter
|
||
ordering="-created_at",
|
||
)
|
||
|
||
for rts in rtstreams:
|
||
print(f"{rts.id}: {rts.name} - {rts.status}")
|
||
```
|
||
|
||
### キャプチャセッションから取得する
|
||
|
||
キャプチャセッションがアクティブになったら、RTStreamオブジェクトを取得する:
|
||
|
||
```python
|
||
session = conn.get_capture_session(session_id)
|
||
|
||
mics = session.get_rtstream("mic")
|
||
displays = session.get_rtstream("screen")
|
||
system_audios = session.get_rtstream("system_audio")
|
||
```
|
||
|
||
または `capture_session.active` WebSocketイベントの `rtstreams` データを使用する:
|
||
|
||
```python
|
||
for rts in rtstreams:
|
||
rtstream = coll.get_rtstream(rts["rtstream_id"])
|
||
```
|
||
|
||
***
|
||
|
||
## RTStreamメソッド
|
||
|
||
| メソッド | 戻り値 | 説明 |
|
||
|--------|---------|-------------|
|
||
| `rtstream.start()` | `None` | 取り込みを開始する |
|
||
| `rtstream.stop()` | `None` | 取り込みを停止する |
|
||
| `rtstream.generate_stream(start, end)` | `str` | 録画されたセグメントをストリーミングする(Unixタイムスタンプ) |
|
||
| `rtstream.export(name=None)` | `RTStreamExportResult` | 永続的なビデオとしてエクスポートする |
|
||
| `rtstream.index_visuals(prompt, ...)` | `RTStreamSceneIndex` | AI分析付きのビジュアルインデックスを作成する |
|
||
| `rtstream.index_audio(prompt, ...)` | `RTStreamSceneIndex` | LLMサマリー付きのオーディオインデックスを作成する |
|
||
| `rtstream.list_scene_indexes()` | `List[RTStreamSceneIndex]` | ストリーム上のすべてのシーンインデックスをリストする |
|
||
| `rtstream.get_scene_index(index_id)` | `RTStreamSceneIndex` | 特定のシーンインデックスを取得する |
|
||
| `rtstream.search(query, ...)` | `RTStreamSearchResult` | インデックス化されたコンテンツを検索する |
|
||
| `rtstream.start_transcript(ws_connection_id, engine)` | `dict` | リアルタイム転写を開始する |
|
||
| `rtstream.get_transcript(page, page_size, start, end, since)` | `dict` | 転写ページを取得する |
|
||
| `rtstream.stop_transcript(engine)` | `dict` | 転写を停止する |
|
||
|
||
***
|
||
|
||
## 開始と停止
|
||
|
||
```python
|
||
# Begin ingestion
|
||
rtstream.start()
|
||
|
||
# ... stream is being recorded ...
|
||
|
||
# Stop ingestion
|
||
rtstream.stop()
|
||
```
|
||
|
||
***
|
||
|
||
## ストリームの生成
|
||
|
||
秒数オフセットではなくUnixタイムスタンプを使用して録画から再生ストリームを生成する:
|
||
|
||
```python
|
||
import time
|
||
|
||
start_ts = time.time()
|
||
rtstream.start()
|
||
|
||
# Let it record for a while...
|
||
time.sleep(60)
|
||
|
||
end_ts = time.time()
|
||
rtstream.stop()
|
||
|
||
# Generate a stream URL for the recorded segment
|
||
stream_url = rtstream.generate_stream(start=start_ts, end=end_ts)
|
||
print(f"Recorded stream: {stream_url}")
|
||
```
|
||
|
||
***
|
||
|
||
## ビデオとしてエクスポートする
|
||
|
||
録画されたストリームをコレクション内の永続的なビデオとしてエクスポートする:
|
||
|
||
```python
|
||
export_result = rtstream.export(name="Meeting Recording 2024-01-15")
|
||
|
||
print(f"Video ID: {export_result.video_id}")
|
||
print(f"Stream URL: {export_result.stream_url}")
|
||
print(f"Player URL: {export_result.player_url}")
|
||
print(f"Duration: {export_result.duration}s")
|
||
```
|
||
|
||
### RTStreamExportResult属性
|
||
|
||
| 属性 | 型 | 説明 |
|
||
|----------|------|-------------|
|
||
| `video_id` | `str` | エクスポートされたビデオのID |
|
||
| `stream_url` | `str` | HLSストリームURL |
|
||
| `player_url` | `str` | Webプレーヤー URL |
|
||
| `name` | `str` | ビデオ名 |
|
||
| `duration` | `float` | 長さ(秒) |
|
||
|
||
***
|
||
|
||
## AIパイプライン
|
||
|
||
AIパイプラインはライブストリームを処理し、WebSocket経由で結果を送信する。
|
||
|
||
### RTStream AIパイプラインメソッド
|
||
|
||
| メソッド | 戻り値 | 説明 |
|
||
|--------|---------|-------------|
|
||
| `rtstream.index_audio(prompt, batch_config, ...)` | `RTStreamSceneIndex` | LLMサマリー付きのオーディオインデックスを開始する |
|
||
| `rtstream.index_visuals(prompt, batch_config, ...)` | `RTStreamSceneIndex` | 画面コンテンツのビジュアルインデックスを開始する |
|
||
|
||
### オーディオインデックス
|
||
|
||
一定間隔でオーディオコンテンツのLLMサマリーを生成する:
|
||
|
||
```python
|
||
audio_index = rtstream.index_audio(
|
||
prompt="Summarize what is being discussed",
|
||
batch_config={"type": "word", "value": 50},
|
||
model_name=None, # optional
|
||
name="meeting_audio", # optional
|
||
ws_connection_id=ws_id,
|
||
)
|
||
```
|
||
|
||
**オーディオのbatch\_configオプション:**
|
||
|
||
| タイプ | 値 | 説明 |
|
||
|------|-------|-------------|
|
||
| `"word"` | count | N単語ごとにセグメント化 |
|
||
| `"sentence"` | count | N文ごとにセグメント化 |
|
||
| `"time"` | seconds | N秒ごとにセグメント化 |
|
||
|
||
例:
|
||
|
||
```python
|
||
{"type": "word", "value": 50} # every 50 words
|
||
{"type": "sentence", "value": 5} # every 5 sentences
|
||
{"type": "time", "value": 30} # every 30 seconds
|
||
```
|
||
|
||
結果は `audio_index` WebSocketチャネル経由で届く。
|
||
|
||
### ビジュアルインデックス
|
||
|
||
ビジュアルコンテンツのAI説明を生成する:
|
||
|
||
```python
|
||
scene_index = rtstream.index_visuals(
|
||
prompt="Describe what is happening on screen",
|
||
batch_config={"type": "time", "value": 2, "frame_count": 5},
|
||
model_name="basic",
|
||
name="screen_monitor", # optional
|
||
ws_connection_id=ws_id,
|
||
)
|
||
```
|
||
|
||
**パラメータ:**
|
||
|
||
| パラメータ | 型 | 説明 |
|
||
|-----------|------|-------------|
|
||
| `prompt` | `str` | AIモデルへの指示(構造化JSON出力をサポート) |
|
||
| `batch_config` | `dict` | フレームサンプリングを制御する(以下を参照) |
|
||
| `model_name` | `str` | モデル層:`"mini"`、`"basic"`、`"pro"`、`"ultra"` |
|
||
| `name` | `str` | インデックス名(オプション) |
|
||
| `ws_connection_id` | `str` | 結果を受信するWebSocket接続ID |
|
||
|
||
**ビジュアルのbatch\_config:**
|
||
|
||
| キー | 型 | 説明 |
|
||
|-----|------|-------------|
|
||
| `type` | `str` | ビジュアルインデックスでは `"time"` のみサポート |
|
||
| `value` | `int` | ウィンドウサイズ(秒) |
|
||
| `frame_count` | `int` | 各ウィンドウで抽出するフレーム数 |
|
||
|
||
例:`{"type": "time", "value": 2, "frame_count": 5}` は2秒ごとに5フレームをサンプリングしてモデルに送信する。
|
||
|
||
**構造化JSON出力:**
|
||
|
||
構造化されたレスポンスを得るためにJSONフォーマットをリクエストするプロンプトを使用する:
|
||
|
||
```python
|
||
scene_index = rtstream.index_visuals(
|
||
prompt="""Analyze the screen and return a JSON object with:
|
||
{
|
||
"app_name": "name of the active application",
|
||
"activity": "what the user is doing",
|
||
"ui_elements": ["list of visible UI elements"],
|
||
"contains_text": true/false,
|
||
"dominant_colors": ["list of main colors"]
|
||
}
|
||
Return only valid JSON.""",
|
||
batch_config={"type": "time", "value": 3, "frame_count": 3},
|
||
model_name="pro",
|
||
ws_connection_id=ws_id,
|
||
)
|
||
```
|
||
|
||
結果は `scene_index` WebSocketチャネル経由で届く。
|
||
|
||
***
|
||
|
||
## バッチ設定のサマリー
|
||
|
||
| インデックスタイプ | `type` オプション | `value` | 追加キー |
|
||
|---------------|----------------|---------|------------|
|
||
| **オーディオ** | `"word"`、`"sentence"`、`"time"` | words/sentences/seconds | - |
|
||
| **ビジュアル** | `"time"` のみ | seconds | `frame_count` |
|
||
|
||
例:
|
||
|
||
```python
|
||
# Audio: every 50 words
|
||
{"type": "word", "value": 50}
|
||
|
||
# Audio: every 30 seconds
|
||
{"type": "time", "value": 30}
|
||
|
||
# Visual: 5 frames every 2 seconds
|
||
{"type": "time", "value": 2, "frame_count": 5}
|
||
```
|
||
|
||
***
|
||
|
||
## 転写
|
||
|
||
WebSocket経由のリアルタイム転写:
|
||
|
||
```python
|
||
# Start live transcription
|
||
rtstream.start_transcript(
|
||
ws_connection_id=ws_id,
|
||
engine=None, # optional, defaults to "assemblyai"
|
||
)
|
||
|
||
# Get transcript pages (with optional filters)
|
||
transcript = rtstream.get_transcript(
|
||
page=1,
|
||
page_size=100,
|
||
start=None, # optional: start timestamp filter
|
||
end=None, # optional: end timestamp filter
|
||
since=None, # optional: for polling, get transcripts after this timestamp
|
||
engine=None,
|
||
)
|
||
|
||
# Stop transcription
|
||
rtstream.stop_transcript(engine=None)
|
||
```
|
||
|
||
転写結果は `transcript` WebSocketチャネル経由で届く。
|
||
|
||
***
|
||
|
||
## RTStreamSceneIndex
|
||
|
||
`index_audio()` または `index_visuals()` を呼び出すと、メソッドは `RTStreamSceneIndex` オブジェクトを返す。このオブジェクトは実行中のインデックスを表し、シーンとアラートを管理するためのメソッドを提供する。
|
||
|
||
```python
|
||
# index_visuals returns an RTStreamSceneIndex
|
||
scene_index = rtstream.index_visuals(
|
||
prompt="Describe what is on screen",
|
||
ws_connection_id=ws_id,
|
||
)
|
||
|
||
# index_audio also returns an RTStreamSceneIndex
|
||
audio_index = rtstream.index_audio(
|
||
prompt="Summarize the discussion",
|
||
ws_connection_id=ws_id,
|
||
)
|
||
```
|
||
|
||
### RTStreamSceneIndex属性
|
||
|
||
| 属性 | 型 | 説明 |
|
||
|----------|------|-------------|
|
||
| `rtstream_index_id` | `str` | インデックスの一意ID |
|
||
| `rtstream_id` | `str` | 親RTStreamのID |
|
||
| `extraction_type` | `str` | 抽出タイプ(`time` または `transcript`) |
|
||
| `extraction_config` | `dict` | 抽出設定 |
|
||
| `prompt` | `str` | 分析に使用するプロンプト |
|
||
| `name` | `str` | インデックス名 |
|
||
| `status` | `str` | 状態(`connected`、`stopped`) |
|
||
|
||
### RTStreamSceneIndexメソッド
|
||
|
||
| メソッド | 戻り値 | 説明 |
|
||
|--------|---------|-------------|
|
||
| `index.get_scenes(start, end, page, page_size)` | `dict` | インデックス化されたシーンを取得する |
|
||
| `index.start()` | `None` | インデックスを開始/再開する |
|
||
| `index.stop()` | `None` | インデックスを停止する |
|
||
| `index.create_alert(event_id, callback_url, ws_connection_id)` | `str` | イベント検出アラートを作成する |
|
||
| `index.list_alerts()` | `list` | このインデックスのすべてのアラートをリストする |
|
||
| `index.enable_alert(alert_id)` | `None` | アラートを有効にする |
|
||
| `index.disable_alert(alert_id)` | `None` | アラートを無効にする |
|
||
|
||
### シーンの取得
|
||
|
||
インデックスからインデックス化されたシーンをポーリングする:
|
||
|
||
```python
|
||
result = scene_index.get_scenes(
|
||
start=None, # optional: start timestamp
|
||
end=None, # optional: end timestamp
|
||
page=1,
|
||
page_size=100,
|
||
)
|
||
|
||
for scene in result["scenes"]:
|
||
print(f"[{scene['start']}-{scene['end']}] {scene['text']}")
|
||
|
||
if result["next_page"]:
|
||
# fetch next page
|
||
pass
|
||
```
|
||
|
||
### シーンインデックスの管理
|
||
|
||
```python
|
||
# List all indexes on the stream
|
||
indexes = rtstream.list_scene_indexes()
|
||
|
||
# Get a specific index by ID
|
||
scene_index = rtstream.get_scene_index(index_id)
|
||
|
||
# Stop an index
|
||
scene_index.stop()
|
||
|
||
# Restart an index
|
||
scene_index.start()
|
||
```
|
||
|
||
***
|
||
|
||
## イベント
|
||
|
||
イベントは再利用可能な検出ルール。一度作成すれば、アラートを通じて任意のインデックスに添付できる。
|
||
|
||
### 接続イベントメソッド
|
||
|
||
| メソッド | 戻り値 | 説明 |
|
||
|--------|---------|-------------|
|
||
| `conn.create_event(event_prompt, label)` | `str` (event\_id) | 検出イベントを作成する |
|
||
| `conn.list_events()` | `list` | すべてのイベントをリストする |
|
||
|
||
### イベントの作成
|
||
|
||
```python
|
||
event_id = conn.create_event(
|
||
event_prompt="User opened Slack application",
|
||
label="slack_opened",
|
||
)
|
||
```
|
||
|
||
### イベントのリスト
|
||
|
||
```python
|
||
events = conn.list_events()
|
||
for event in events:
|
||
print(f"{event['event_id']}: {event['label']}")
|
||
```
|
||
|
||
***
|
||
|
||
## アラート
|
||
|
||
アラートはイベントをインデックスに接続してリアルタイム通知を実現する。AIがイベントの説明に一致するコンテンツを検出すると、アラートが送信される。
|
||
|
||
### アラートの作成
|
||
|
||
```python
|
||
# Get the RTStreamSceneIndex from index_visuals
|
||
scene_index = rtstream.index_visuals(
|
||
prompt="Describe what application is open on screen",
|
||
ws_connection_id=ws_id,
|
||
)
|
||
|
||
# Create an alert on the index
|
||
alert_id = scene_index.create_alert(
|
||
event_id=event_id,
|
||
callback_url="https://your-backend.com/alerts", # for webhook delivery
|
||
ws_connection_id=ws_id, # for WebSocket delivery (optional)
|
||
)
|
||
```
|
||
|
||
**注意:** `callback_url` は必須。WebSocket配信のみを使用する場合は空文字列 `""` を渡す。
|
||
|
||
### アラートの管理
|
||
|
||
```python
|
||
# List all alerts on an index
|
||
alerts = scene_index.list_alerts()
|
||
|
||
# Enable/disable alerts
|
||
scene_index.disable_alert(alert_id)
|
||
scene_index.enable_alert(alert_id)
|
||
```
|
||
|
||
### アラート配信
|
||
|
||
| 方法 | 遅延 | ユースケース |
|
||
|--------|---------|----------|
|
||
| WebSocket | リアルタイム | ダッシュボード、ライブUI |
|
||
| Webhook | < 1秒 | サーバー間、自動化 |
|
||
|
||
### WebSocketアラートイベント
|
||
|
||
```json
|
||
{
|
||
"channel": "alert",
|
||
"rtstream_id": "rts-xxx",
|
||
"data": {
|
||
"event_label": "slack_opened",
|
||
"timestamp": 1710000012340,
|
||
"text": "User opened Slack application"
|
||
}
|
||
}
|
||
```
|
||
|
||
### Webhookペイロード
|
||
|
||
```json
|
||
{
|
||
"event_id": "event-xxx",
|
||
"label": "slack_opened",
|
||
"confidence": 0.95,
|
||
"explanation": "User opened the Slack application",
|
||
"timestamp": "2024-01-15T10:30:45Z",
|
||
"start_time": 1234.5,
|
||
"end_time": 1238.0,
|
||
"stream_url": "https://stream.videodb.io/v3/...",
|
||
"player_url": "https://console.videodb.io/player?url=..."
|
||
}
|
||
```
|
||
|
||
***
|
||
|
||
## WebSocket統合
|
||
|
||
すべてのリアルタイムAI結果はWebSocket経由で配信される。以下に `ws_connection_id` を渡す:
|
||
|
||
* `rtstream.start_transcript()`
|
||
* `rtstream.index_audio()`
|
||
* `rtstream.index_visuals()`
|
||
* `scene_index.create_alert()`
|
||
|
||
### WebSocketチャネル
|
||
|
||
| チャネル | ソース | コンテンツ |
|
||
|---------|--------|---------|
|
||
| `transcript` | `start_transcript()` | リアルタイム音声テキスト変換 |
|
||
| `scene_index` | `index_visuals()` | ビジュアル分析結果 |
|
||
| `audio_index` | `index_audio()` | オーディオ分析結果 |
|
||
| `alert` | `create_alert()` | アラート通知 |
|
||
|
||
WebSocketイベント構造とws\_listenerの使用については [capture-reference.md](capture-reference.md) を参照。
|
||
|
||
***
|
||
|
||
## 完全なワークフロー
|
||
|
||
```python
|
||
import time
|
||
import videodb
|
||
from videodb.exceptions import InvalidRequestError
|
||
|
||
conn = videodb.connect()
|
||
coll = conn.get_collection()
|
||
|
||
# 1. Connect and start recording
|
||
rtstream = coll.connect_rtstream(
|
||
url="rtmp://your-stream-server/live/stream-key",
|
||
name="Weekly Standup",
|
||
store=True,
|
||
)
|
||
rtstream.start()
|
||
|
||
# 2. Record for the duration of the meeting
|
||
start_ts = time.time()
|
||
time.sleep(1800) # 30 minutes
|
||
end_ts = time.time()
|
||
rtstream.stop()
|
||
|
||
# Generate an immediate playback URL for the captured window
|
||
stream_url = rtstream.generate_stream(start=start_ts, end=end_ts)
|
||
print(f"Recorded stream: {stream_url}")
|
||
|
||
# 3. Export to a permanent video
|
||
export_result = rtstream.export(name="Weekly Standup Recording")
|
||
print(f"Exported video: {export_result.video_id}")
|
||
|
||
# 4. Index the exported video for search
|
||
video = coll.get_video(export_result.video_id)
|
||
video.index_spoken_words(force=True)
|
||
|
||
# 5. Search for action items
|
||
try:
|
||
results = video.search("action items and next steps")
|
||
stream_url = results.compile()
|
||
print(f"Action items clip: {stream_url}")
|
||
except InvalidRequestError as exc:
|
||
if "No results found" in str(exc):
|
||
print("No action items were detected in the recording.")
|
||
else:
|
||
raise
|
||
```
|