editframe-api について
Editframeのクラウド動画APIやローカルプロジェクトを扱う開発者向けのJavaScript/TypeScriptクライアントとCLIです。レンダリング、メディア処理、インストール済みランタイム経由のローカル書き出しに対応します。
主な機能
- 01レンダリングの作成と進捗確認
- 02動画・画像・字幕ファイルのアップロード
- 03パイプラインによる音声文字起こし
- 04メディアアクセス用URLの署名
- 05エディターを開いてローカル書き出しを送信
活用シーン
- 01Editframeのコンポジションから動画をレンダリング
- 02メディア素材のアップロードと処理
- 03パイプラインで音声アノテーションを生成
- 04ローカルプロジェクトの書き出しを送信・確認
MCP 対応
CLIの`mcp`コマンドは、MCP stdio経由でエージェントをローカルbridgeに接続します。Editframeのエージェントパッケージにはホスト設定が含まれます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ editframe/ skills --skill editframe-apiインストール後、Claude Code で/editframe-apiを入力して読み込まれたか確認します。
詳細
Editframe API と CLI
@editframe/api は、Editframe のクラウド動画 API 用 JavaScript/TypeScript クライアントです。Editframe のコンポジションから動画をレンダリングしたり、メディアファイルをアップロードして処理したり、音声を書き起こすパイプラインを実行したり、CDN リソースへの認証済みブラウザーアクセスを管理したりできます。
editframe CLI は、インストール済みの Editframe ランタイム用の薄いクライアントです。ブラウザーエディターを開き、ローカルプロジェクトのエクスポートをリクエストします。CLI を参照してください。
クイックスタート
import { Client, createRender, getRenderProgress, downloadRender } from "@editframe/api";
const client = new Client(process.env.EDITFRAME_API_KEY);
const render = await createRender(client, {
html: `<ef-timegroup mode="contain" class="w-[1920px] h-[1080px]">
<ef-video src="https://assets.editframe.com/bars-n-tone.mp4"></ef-video>
</ef-timegroup>`,
width: 1920,
height: 1080,
fps: 30,
});
for await (const event of await getRenderProgress(client, render.id)) {
if (event.type === "progress") console.log(`Progress: ${(event.data.progress * 100).toFixed(0)}%`);
}
const response = await downloadRender(client, render.id);
const buffer = await response.arrayBuffer();
クライアントと認証
import { Client } from "@editframe/api";
const client = new Client(process.env.EDITFRAME_API_KEY); // server-side: Bearer token
const client = new Client(); // browser: session cookie (credentials: "include")
const client = new Client(apiKey, "https://staging.editframe.com"); // optional second arg overrides the host (default https://editframe.com)
API キーの形式は ef_<secret>_<keyid> です。クライアントはこの形式をローカルで検証します。Editframe ダッシュボードの「API → API Keys」からキーを取得してください。エラーの動作は SDK 関数によって異なります。拒否されたリクエストと、ドキュメントに記載されている結果の状態を処理してください。
API キーをクライアントサイドのコードで絶対に公開しないでください。 認証が必要なメディアをブラウザーで再生する場合は、代わりにURL 署名を使用してください。キーはサーバーに保持します。ブラウザーには、有効期間が短く、スコープが限定されたトークンのみを渡します。
@editframe/api では、createImageFile、createCaptionFile、createISOBMFFFile など、型ごとの古いリソースも引き続きエクスポートされます。これらは統一された createFile/type: "video"|"image"|"caption" API の使用が推奨されており、@deprecated です。新しいコードでは使用しないでください。廃止された書き起こし関数については、書き起こしを参照してください。
統一ファイル API
動画、画像、キャプションのすべてのファイル形式で、同じエンドポイント一式を使用します。type フィールドによって、エンドポイントの動作が決まります。
| 種類 | 形式 | 最大サイズ | 処理 |
|---|---|---|---|
video | MP4、MOV、WebM、MKV | 1GB | ISOBMFF に自動変換(フレーム単位の正確なシークとアダプティブストリーミングに対応) |
image | JPEG、PNG、WebP、SVG | 16MB | すぐに利用可能 |
caption | VTT、SRT | 2MB | すぐに利用可能 |
ステータスのライフサイクル:created → uploading → processing → ready(画像/キャプションでは processing をスキップ)、または → failed です。
import { Client, createFile, uploadFile, getFileProcessingProgress } from "@editframe/api";
import { createReadStream } from "node:fs";
import { stat } from "node:fs/promises";
import { Readable } from "node:stream";
const client = new Client(process.env.EDITFRAME_API_KEY);
const fileStats = await stat("video.mp4");
const file = await createFile(client, { filename: "video.mp4", type: "video", byte_size: fileStats.size });
for await (const event of uploadFile(client, { id: file.id, byte_size: fileStats.size, type: "video" }, Readable.toWeb(createReadStream("video.mp4")))) {
if (event.type === "progress") console.log(`Upload: ${(event.progress * 100).toFixed(1)}%`);
}
for await (const event of await getFileProcessingProgress(client, file.id)) {
if (event.type === "complete") break;
}
uploadFile は Web の ReadableStream を受け取ります。上記のように、Node のストリームは Readable.toWeb で変換してください。ブラウザーファイルでは、file.stream() から互換性のあるストリームを取得できます。
Node ヘルパーはファイルレコードを作成し、遅延アップロードイテレーターを返します。ファイルのバイト列をアップロードするには、このイテレーターを消費します。
import { Client, upload, getFileProcessingProgress } from "@editframe/api/node";
const client = new Client(process.env.EDITFRAME_API_KEY);
const { file, uploadIterator } = await upload(client, "video.mp4");
for await (const event of uploadIterator) {
console.log(`Upload: ${(event.progress * 100).toFixed(1)}%`);
}
for await (const event of await getFileProcessingProgress(client, file.id)) {
if (event.type === "complete") break;
}
アップロードの完了とメディア処理の完了は、それぞれ別の状態です。
アップロードする前に、既存のファイルを確認してください。lookupFileByMd5(client, md5) を呼び出します。一致するファイルがない場合は null が返されます。
file-id を使って、コンポジション内でファイルを使用します。
<ef-configuration api-host="https://editframe.com">
<ef-video file-id="uuid-of-processed-video"></ef-video>
<ef-image file-id="uuid-of-uploaded-image" class="w-24 h-24"></ef-image>
</ef-configuration>
createFile は、安定した UUID を file-id として割り当てます。アップロード、処理、再生を通じて同じ値が維持されます。
保持期間(expires_at)
createFile と createRender は、どちらも省略可能な expires_at を受け取ります。これは ISO 8601 形式の日付で、指定できるのは未来 30 日以内までです。永続的に保持する場合は省略してください。無効な入力には、invalid_datetime、must_be_future、exceeds_max_retention のいずれかとともに 400 が返されます。getFileDetail と getRenderInfo は expires_at を返します。null は永続的な保持を意味します。リモート URL からのレンダー取り込み(以下を参照)では、固定された設定変更不可の 1 時間 TTL が使用されます。これはこのフィールドとは無関係です。
レンダリング
const render = await createRender(client, {
html: `<ef-timegroup mode="contain" class="w-[1920px] h-[1080px]"><ef-video src="..."></ef-video></ef-timegroup>`,
width: 1920,
height: 1080,
fps: 30, // default 30
output: { container: "mp4", video: { codec: "h264" }, audio: { codec: "aac" } }, // default shown
});
出力コンテナ:mp4(video.codec: "h264"、audio.codec: "aac")、jpeg(quality 1~100、デフォルトは80)、png(compression 1~100、デフォルトは80、transparency はブール値)、webp(quality 1~100、デフォルトは80、compression 0~6、デフォルトは4、transparency はブール値)。
createRender では、以下の高度なオプションも指定できます。
- サーバー設定によって実行バックエンドが選択されます。SDK の
backendフィールドで現在のサーバーフラグを上書きすることはできません。 work_slice_ms:レンダリングをこの長さ(ミリ秒)のフラグメントに分割します。デフォルトは"cpu"では4000、"gpu"では15000です。最大値は60000です。strategy:今後のレンダリング戦略用に予約されています。現在は"v1"のみで、これがデフォルトです。duration_ms:検出されたレンダリング時間をミリ秒単位で上書きします。metadata:任意のRecord<string, string>です。getRenderInfoとレンダリング Webhook は、この値をそのまま返します。
コンポジションの ef-video、ef-audio、ef-image 要素では、https:// の src 値を直接使用できます。Editframe はレンダリング前にこれらをダウンロードして取り込み、有効期限は約1時間の一時的な expires_at になります。これは createFile で登録するファイルとは異なります。
以前のレンダリングを再利用する場合は、明示的に lookupRenderByMd5 を呼び出してください。createRender はこの検索を実行しません。
出力設定や安定したアセットのバージョンを含む、レンダリング入力全体からハッシュを生成してください。HTML だけをハッシュすると、これらの違いが反映されません。
再利用する前に、レンダリングの完了状態、出力設定、保持期間を確認してください。ハッシュが一致しても、結果を利用できるとは限りません。
getRenderProgress は { type: "progress", data: { progress } } を返します。progress は0から1までの値で、その後 { type: "complete" } を返します。レンダリングに失敗するとエラーをスローします。deleteRender は行と GCS の出力および中間ファイルをすぐに削除します。レンダリングが queued、rendering、recovering のいずれかの状態で実行中の場合は失敗します。
自分でレンダリングした動画を登録するには、html を省略してファイルを直接アップロードします。
import { createReadStream } from "node:fs";
import { Readable } from "node:stream";
const render = await createRender(client, { width: 1920, height: 1080, fps: 30 });
await uploadRender(client, render.id, Readable.toWeb(createReadStream("my-video.mp4")));
文字起こし
ファイルを文字起こしするには、transcribe ステップを含むパイプライン実行を開始します。パイプラインを参照してください。このステップは speech.segment と speech.word のアノテーションを書き込みます。getPipelineRunOutputs(client, runId, namespace) で読み取れます。
従来の文字起こし機能は廃止されています。transcribeFile、transcribeISOBMFFFile、createTranscription は @deprecated です。これらのエンドポイントは、エラー transcription_retired とともに 410 Gone を返します。使用しないでください。
getFileTranscription は、従来の文字起こしの状態(id、status、completed_at、failed_at、work_slice_ms)を引き続き報告します。文字起こしのセグメントは返しません。従来の文字起こしがないファイルの場合は null を返します。
ef-captions には、captions-src、captions-script、または captions.captionsData からキャプションデータを渡す必要があります。target は、参照先の ef-video/ef-audio 要素のローカル時間にキャプションのタイミングを同期するだけです。文字起こしデータは取得しません。composition スキルの ef-captions リファレンスを参照してください。
URL 署名
ブラウザーが Editframe ホストのメディアを直接再生する場合は、<ef-video src="https://editframe.com/api/v1/transcode/..."> のように、URL 署名を使用してください。createRender/downloadRender を通じて、すべてのレンダリングと再生がサーバー側で行われる場合は不要です。
サーバーで API キーを保持し、createURLToken を呼び出すエンドポイントを公開します。
祖先の ef-configuration に HTML 属性 signing-url を設定してください。JavaScript プロパティ名は signingURL です。
トークンを発行する前に、呼び出し元を認証し、要求されたメディアへのアクセス権を確認してください。
ブラウザーは { url } をそのエンドポイントに送信し、返されたトークンをメディアリクエストに付加します。
トークンの有効期間は約 1 時間です。ブラウザーは URL ごとに各トークンをキャッシュします。トランスコードまたは HLS エンドポイントでは、マニフェストとすべてのセグメントを 1 つのトークンで扱えます。
// Inside your authenticated application router, authorize access to the requested media URL.
import { Client, createURLToken } from "@editframe/api";
const client = new Client(process.env.EDITFRAME_API_KEY);
app.post("/sign-url", async (req, res) => res.json({ token: await createURLToken(client, req.body.url) }));
<ef-configuration api-host="https://editframe.com" signing-url="/sign-url">
<ef-video src="https://editframe.com/api/v1/transcode/manifest.m3u8?url=..."></ef-video>
</ef-configuration>
API キーの代わりに editframe.com のセッション Cookie を使う場合は、Authorization ヘッダーを付けず、credentials: "include" を指定して POST /ef-sign-url を使用してください。これは同等の匿名トークンフローです。多くのアプリでは、上記の API キーを使うサーバールートを使用します。
CLI
editframe CLI は、インストール済みの Editframe ランタイム用の薄いクライアントです。ブリッジ、エディター、レンダリング依存関係はバンドルされません。まず https://editframe.com/agent からランタイムをインストールしてください。
npm install -D @editframe/cli # already included in the html/react scaffolds
各ローカルコマンドには --project とブリッジが必要です。--bridge、--component、EDITFRAME_BRIDGE_PATH、または EDITFRAME_COMPONENT_ROOT でブリッジを選択してください。各コマンドは JSON を出力します。
export EDITFRAME_BRIDGE_PATH=/absolute/editframe-bridge
npx editframe start --project .
npx editframe open --project . # prints an editor URL; keep it private
npx editframe compositions --project .
npx editframe context --project . --composition COMPOSITION_ID
context は、現在のリビジョン ID と、サポートされているエクスポート設定を返します。エクスポートするには、新しい operation_id、その revision_id、およびサポートされている設定を含むリクエストファイルを作成します。
{
"operation_id": "export-demo-001",
"revision_id": "REPLACE_WITH_CURRENT_REVISION_ID",
"execution_target": "local",
"settings": { "container": "mp4", "video_codec": "h264", "audio_codec": "aac", "width": 1280, "height": 720, "fps": 30 }
}
npx editframe export --project . --composition COMPOSITION_ID --input export.json
npx editframe job --project . --job JOB_ID
- ローカルエクスポート中は、ブラウザーエディターを開いたままにしてください。エディターがレンダラーです。
- CLI はジョブを送信して確認します。動画ファイルは書き出しません。ファイルはエディターから取得してください。
operation_idは、同じ内容の再試行に限り再利用してください。新しいリビジョンまたは新しい設定には、新しいoperation_idが必要です。commandは、リビジョン管理されたコンポジション編集を 1 件適用します。--inputファイルには、operation_id、base_revision_id、kind、labelが必要です。リビジョンの競合が発生したら、もう一度contextを読み込み、新しいoperation_idを使用してください。mcpは、MCP stdio を介してエージェントをローカルブリッジに接続します。ネイティブエージェントのパッケージには、https://editframe.com/agent のホスト設定が含まれています。
有効化されたホスト型ランタイムでは、--project とブリッジを --endpoint および --project-id に置き換えてください。環境変数に EDITFRAME_TOKEN を設定します。以前の CLI の EF_TOKEN 変数は、ランタイムへのログインには使用できません。
このファイル末尾の生成済みテーブルには、@editframe/cli パーサーの各オプションとコマンドが記載されています。
以前のコマンド
次のコマンド名は、現在 CLI_MIGRATION_REQUIRED エラーになります。
| 以前のコマンド | 現在の方法 |
|---|---|
preview、dev、dev-server | start と open、または Vite および Next.js アダプターを使用してください。dev-server スキルを参照してください。 |
render | export を使用するか、ブラウザーエディターからエクスポートしてください |
auth、cloud-render、sync | @editframe/api の createRender と統合ファイル API を使用してください |
webhook | API キーの Webhook URL を変更してください。webhooks スキルを参照してください。 |
check、process、process-file、transcribe | CLI での代替手段はありません。ブラウザーエディターを使用してください。アプリのビルドでは @editframe/build-adapter を使用します。 |
パイプライン
Editframe は、各組織でパイプラインを有効にします。パイプラインを利用するには、https://editframe.com/factory#contact で Editframe にフッテージについてお知らせください。パイプラインのない組織では、すべてのパイプラインルートが 404 を返します。
パイプライン関数は @editframe/api/pipelines からインポートしてください。このエントリーポイントは実験的なもので、メジャーバージョンの変更を伴わずに変更される場合があります。このファイル末尾の関数インデックスには記載されていません。
パイプラインは、不変のバージョンを持つ、名前付きのステップグラフです。1 回の実行では、1 つのバージョンを通じて 1 つの video ファイルを処理します。ステップは、needs に指定されたステップが完了した後に開始されます。各ステップは、ファイル上の名前空間に出力を書き込みます。
import { Client, createPipeline, createPipelineRun, getPipelineRun, isPipelineRunTerminal } from "@editframe/api/pipelines";
const client = new Client(process.env.EDITFRAME_API_KEY);
const pipeline = await createPipeline(client, {
name: "speech-check",
definition: {
steps: {
probe: { type: "probe" },
transcript: { type: "transcribe", needs: ["probe"] },
has_speech: { type: "filter", needs: ["transcript"], when: { path: "transcript.metadata.word_count", op: "gt", value: 0 } },
publish: { type: "publish", needs: ["has_speech"] },
},
},
});
const { run } = await createPipelineRun(client, { pipeline_id: pipeline.id, file_id: fileId }, { idempotencyKey: `speech-check:${fileId}` });
let current = await getPipelineRun(client, run.id);
while (!isPipelineRunTerminal(current)) {
await new Promise((resolve) => setTimeout(resolve, 5000));
current = await getPipelineRun(client, run.id);
}
定義
定義は、1~64 個のステップを持つ { steps: { <key>: step } } です。ステップキーと名前空間は ^[a-z][a-z0-9_]{0,62}$ に一致します。不明なフィールドがある場合、422 エラーになります。
| ステップのフィールド | ルール |
|---|---|
type | 必須です。以下のいずれかのタイプを指定します。 |
needs | 先に完了する必要があるステップのキーです。最大 16 個です。デフォルトは [] です。循環は許可されません。 |
namespace | 一意である必要があります。デフォルトはステップキーです。 |
granularity | { mode: "file" }(デフォルト)、または { mode: "segment", window_ms: 1000–3600000, overlap_ms: 0 to window_ms/2 } |
with | タイプのオプションです。 |
when | filter では必須です。他のタイプでは指定できません。 |
| タイプ | with(デフォルト) | 出力 |
|---|---|---|
probe | 指定できません | メタデータ duration_ms、width、height、has_video、has_audio、source、tracks |
transcribe | 指定できません | speech.segment および speech.word アノテーション。メタデータ word_count、segment_count、truncated など。 |
sample_frames | every_ms 100–600000(1000) | 最初のビデオトラックの JPEG フレーム |
detect_scenes | threshold 0.01–1(0.3) | scene.cut アノテーション。メタデータ cut_count。 |
endpoint | endpoint_id(必須)、max_concurrency 1–1024(8) | サービスの出力 |
filter | 指定できません | 出力なし。ステップは成功するか、スキップされます。 |
review | instructions 1~2000 文字、expires_after_ms 60000~2592000000(604800000)、on_expiry fail/approve/reject(fail) | 判定と修正済みアノテーション |
redact_render | kinds:1~32 個のアノテーション種別(必須)、captions ブール値(false)、title:{ text: 1~120 文字, duration_ms: 1000~15000(4000) } | メタデータ render_id、status、output_url、output_file_id、および各種件数 |
publish | formats:hls および/または dash(["hls"]) | メタデータ file_id、source_url、hls_url、dash_url |
次のルールに従ってください。
segmentの粒度は、transcribe、sample_frames、detect_scenes、endpointにのみ使用してください。- アップロードの完了前にセグメントステップを開始するには、そのステップの
needsをすべてセグメントステップにしてください。ファイルステップはファイル全体の準備が完了するまで待機します。 - ウィンドウはフラグメントの境界から開始します。ウィンドウは
window_msより長くなる場合があります。セグメントアノテーションは、そのウィンドウ内に収める必要があります。 publishは入力ファイルの再生 URL を返します。publishがredact_renderステップに依存する場合は、ぼかし処理済みファイルを再生します。ぼかし処理がskippedの場合は、入力ファイルを再生します。file_idは再生するファイルを示します。publishステップが直接または間接的に依存できるredact_renderステップは 1 つだけです。複数ある場合、needsでnot_allowedエラーになります。redact_renderは、keyframesを含むアノテーションをぼかし、含まないアノテーションをミュートします。レンダリング分数を消費する通常のレンダリングを作成します。その後、そのレンダリングを新しいファイル(output_file_id)として組織に追加します。このステップは、そのファイルの準備が完了すると成功します。レンダリングまたはファイルに失敗しても、自動的には再試行されません。実行を再試行すると、再度レンダリングされます。captions: trueの場合、redact_renderはtranscribeステップの文字起こしから字幕を焼き込みます。このステップは、直接または間接的に、1 つのtranscribeステップにのみ依存する必要があります。transcribeステップがない場合、with.captionsでnot_upstreamエラーになります。複数ある場合はnot_allowedエラーになります。ミュートされた単語は字幕に表示されません。代わりに▇▇▇が表示されます。titleが指定されている場合、redact_renderは動画の上部にtitle.textを表示します。タイトルはduration_msの時点でフェードアウトします。Editframe はテキストの先頭と末尾の空白を削除します。- 字幕またはタイトルを含む
redact_renderステップは、ぼかす対象が何もない場合も常にレンダリングします。そのメタデータにはcaption_countとtitle_appliedも含まれます。 - Editframe は定義を正規化し、
sha256:ダイジェストを記録します。同等の定義は同じダイジェストになります。
フィルター
フィルターは when を評価します。述語が true の場合、フィルターは成功します。述語が false の場合、フィルターとそれ以降のすべてのステップがスキップされます。
- 葉は
{ path, op, value }です。pathは<namespace>.metadata.<field>...または<namespace>.annotations...です。数値のセグメントは配列項目を選択します。 opはexists、non_empty、eq、ne、gt、gte、lt、lte、in(スカラー値を1~64個指定)またはcontainsです。- 葉は
{ all: [...] }、{ any: [...] }(子要素は1~16個)および{ not: predicate }で組み合わせます。最大深度は4です。 pathに値がない場合、すべての葉は false になります。これにはneも含まれます。- フィルターが読み取れるのは、直接的または間接的に必要とするステップの名前空間のみです。それ以外のパスは
not_upstreamになります。 - セグメントステップの場合、フィルターはすべてのウィンドウの注釈を読み取ります。各メタデータフィールドについては、そのフィールドを設定した最後のウィンドウの値を読み取ります。
最終ステップとは、ほかのステップから必要とされていないステップです。最終ステップが1つ以上成功すると、実行は succeeded で終了します。フィルターまたはレビューによって、すべてのブランチが最終ステップに到達する前に停止した場合、実行は filtered で終了します。相互に補完する2つのフィルターがある場合、選択されたブランチが完了すると、実行は succeeded で終了します。Editframe は、両方のブランチを必要とするステップを常にスキップします。
レビュー
レビューのステップではレビュータスクが開かれ、waiting_review の状態で待機します。
approvePipelineReview(client, id, { metadata_patch })はステップを成功させます。パッチは{ annotations, reviewed_kinds? }です。パッチ内の各 kind は、後続のステップでその kind の以前の注釈を置き換えます。注釈なしでreviewed_kindsに含まれる kind は、後続のステップでその kind が削除されます。rejectPipelineReview(client, id, { reason })はステップとそれ以降のステップをスキップします。reasonの文字数は最大2000文字です。- 有効期限が切れたとき、
on_expiry: "approve"はステップを成功させ、"reject"はスキップし、"fail"は実行を失敗させます。実行を再試行すると、新しいレビュータスクが開きます。 - 2回目の判断が最初の判断と異なる場合は
409 review_conflictを返します。期限後の判断は409 review_expiredまたは409 review_not_pendingを返します。同じ判断を再度行った場合は、記録済みの判断を返します。 getPipelineReviewは、実行のstepsの順序でinput_namespacesを返します。それぞれをgetPipelineRunOutputs(client, review.run_id, namespace)で読み取ります。
エンドポイントの手順
createPipelineEndpoint(client, { url, headers, timeout_ms, callback_timeout_ms, max_concurrency }) でサービスを登録します。
urlには HTTPS を使用し、パブリックアドレスに解決される必要があります。headersは最大 16 個設定できます。- デフォルト値:
timeout_msは 30000(1000~600000)、callback_timeout_msは 3600000(1000~2592000000)、max_concurrencyは 8(1~1024、すべての実行を対象)。 - レスポンスには
signing_secret(whsec_...)が一度だけ含まれます。すぐに保存してください。 - 制限を変更するには、
updatePipelineEndpoint(client, id, { timeout_ms, callback_timeout_ms, max_concurrency })を使用します。変更する制限のみを送信してください。範囲は同じです。変更後に送信されたリクエストには新しい制限が適用されます。 - ボディが空の場合、または値が範囲外の場合は
422 invalid_requestが返されます。アーカイブ済みのエンドポイントの場合は409 endpoint_archivedが返されます。 - URL、ヘッダー、署名シークレットは変更できません。変更するには、新しいエンドポイントと新しいパイプラインバージョンを作成してから、古いエンドポイントをアーカイブします。
- バージョンでアーカイブ済みのエンドポイントを指定している実行は、
endpoint_not_foundで失敗します。
Editframe は Standard Webhooks ヘッダーを含む署名付きの POST を送信します。ボディには file、window(ファイルステップの場合は null)、media の URL、metadata(名前空間ごとに必要なステップの出力)、idempotency_key、callback が含まれます。メディア URL に API キーは不要で、media.expires_at に期限切れになります(最長 4 時間後)。
import { postPipelineCallback, verifyPipelineEndpointRequest } from "@editframe/api/pipelines";
// Pass the raw body bytes. Re-serialized JSON does not verify.
const request = await verifyPipelineEndpointRequest({ secret: process.env.EDITFRAME_ENDPOINT_SECRET!, headers: req.headers, body: rawBody });
// Option 1: answer 200 with { metadata, annotations }.
// Option 2: answer 202, and then post the result:
await postPipelineCallback(request.callback.url, { status: "succeeded", output: { metadata: {}, annotations: [] } });
202以外の2xxレスポンスは出力を返します。ボディが空の場合は、空の出力が返されます。408、429、5xxレスポンス、タイムアウト、または接続エラーが発生すると、再試行が開始されます。最大 1 時間のRetry-Afterで遅延時間を指定できます。- リダイレクトまたはその他の
4xxレスポンスの場合、ステップは再試行されずに失敗します。 202の後、期限前に{ status: "heartbeat" }を投稿すると、期限がcallback_timeout_msだけ延長されます。- 失敗を報告するには、
{ status: "failed", error: { message, code?, retryable } }を投稿します。 - 待機していない試行へのコールバックは
409 step_not_waitingを返します。
出力は { metadata?, annotations? } で、最大 1 MiB、注釈は最大 10,000 件です。注釈には kind、start_ms、end_ms が含まれます。また、label、text、confidence(0~1)、track_id、keyframes を含めることもできます。キーフレームは、正規化された 0~1 のフレーム座標で表される { t_ms, x, y, w, h } です。
実行、グループ、出力
createPipelineRun(client, { pipeline_id, version?, group_id?, file_id, external_id?, metadata? }, { idempotencyKey })は{ run, created }を返します。ファイルのタイプはvideoである必要があります。デフォルトのバージョンは最新です。- 同一のリクエストに限り、
idempotencyKeyを再利用できます。異なるボディを送信すると409 idempotency_conflictが返されます。 metadataは文字列のマップです。キーは最大 32 個で、それぞれ 1~256 バイト、値はそれぞれ最大 1024 バイト、コンパクトな JSON で最大 8192 バイトです。実行の作成後に変更することはできません。ステップが書き込むファイルのメタデータとは異なります。listPipelineRuns(client, { status, pipeline_id, file_id, group_id, metadata })は、実行を新しい順に返します。metadataフィルターを指定すると、すべてのエントリーに一致する実行のみが返されます。- パイプライン、バージョン、エンドポイント、実行、グループには
created_byとcreated_viaがあります。created_byは{ type: "api_key" | "user", id }で、リクエストを送信した API キー、またはダッシュボードを使用したか API キーなしでリクエストを送信したユーザーを表します。created_viaは"api"または"dashboard"です。Editframe が作成者を記録していない場合、どちらもnullです。
グループには、1 つのパイプラインバージョンの実行がまとめられます。グループを使用すると、一連の実行を追跡し、同時に実行する実行数を制限し、すべての実行が完了したときにイベントを 1 つ受け取ることができます。
createPipelineGroup(client, { pipeline_id, version?, runs?, close?, max_in_flight?, external_id?, metadata? }, { idempotencyKey })は{ group, created }を返します。runsには、異なるファイルを対象とする 0~1000 件のエントリーを指定します:{ file_id, external_id?, metadata? }。実行はグループのメタデータを継承しません。max_in_flightは 1~100000 で、デフォルトは 100 です。その他の実行はpendingのままになり、古いものから順に開始されます。- 上限を変更するには、
updatePipelineGroup(client, id, { max_in_flight })またはeditframe pipelines groups update GROUP_ID --max-in-flight Nを使用します。グループのすべてのステータスで変更できます。上限を引き上げると、待機中の実行がすぐに開始されます。引き下げても、実行中の実行は継続します。 - Editframe は、クローズのたび、および
max_in_flightの変更のたびに、それを行った API キーまたはユーザーを記録します。ダッシュボードでこの変更履歴を確認できます。現在の値と同じ値への変更は記録されません。 - 後から実行を追加するには、
group_idを指定してcreatePipelineRunを呼び出します。実行はグループのバージョンを使用します。グループとpipeline_idまたはversionが異なる場合、404 group_not_found、409 group_closed、409 group_version_mismatchが返されます。 - グループのステータスは、
open(実行を受け付ける)、closed(実行を受け付けず、一部の実行が未完了)、completed(クローズ済みで、すべての実行が完了)です。 openのグループは完了しません。最後の実行後にclosePipelineGroup(client, id)を呼び出すか、グループ作成時にclose: trueを指定してください。すべての実行が完了したグループは、クローズすると完了します。completedのグループ内の実行を再試行すると、グループは再びclosedになります。completion_countは完了回数をカウントします。listPipelineGroups(client, { status, pipeline_id, metadata })とgetPipelineGroup(client, id)は、実行数を含むグループを返します。getPipelineGroupReport(client, id)は、ステータスごとの実行数、queue_wait_msとrun_duration_ms(p50、p95、max)、入力のmedia_minutes、エラーコードの頻度上位 5 件を含むstep_failures、およびusageを返します。
実行とステップ:
- 実行ステータスは、
pending、running、succeeded、failed、filtered、cancelledです。filteredは、フィルターまたはレビューによって、すべてのブランチが最終ステップの前に停止したことを意味します。これはエラーではありません。停止したブランチがあっても、最終ステップが成功すれば、実行はsucceededで終了します。 - ステップステータスは、
pending、ready、running、waiting_external、waiting_review、succeeded、failed、skipped、cancelledです。 getPipelineRunは、深さ、次にステップキーの順でstepsを返します。needsを持たないステップの深さは 0 です。別のステップの深さは、そのneedsに含まれるステップの深さの最大値に 1 を加えた値です。つまり、各ステップは依存するステップの後に実行されます。- 各ステップまたはウィンドウの試行回数は 3 回です。再試行の待機時間は 10 秒から始まり、最大 10 分まで倍増します。
transcribe、sample_frames、またはdetect_scenesの試行は、たとえばワーカーのメモリ不足などでデコーダーが停止すると、decoder_killedで失敗します。この失敗により再試行が開始されます。ステップでデコードできないファイルはdecode_failedで失敗し、再試行は開始されません。- 成功、失敗、または
filteredで終了した実行に対してcancelPipelineRunを呼び出すと、409 run_not_cancellableが返されます。 retryPipelineRunは、failedとcancelledの実行にのみ使用できます。それ以外の実行では409 run_not_retryableが返されます。成功したステップの出力は保持されます。getPipelineRunOutputs(client, runId, namespace)は、セグメントステップの各ウィンドウにつき 1 ページの出力を返します。getFilePipelineMetadata(client, fileId, namespace)は、あらゆる実行によるファイル上の最新の出力を返します。- リクエストが失敗すると、
status、code、issues([{ path, code }])を含むPipelineApiErrorがスローされます。
アップロード完了前に実行を開始するには、@editframe/api/pipelines/upload の uploadFragmented を使用してアップロードします。onCreated で実行を開始してください。セグメントステップは、メディアが届くたびに各ウィンドウを処理します。
import { uploadFragmented } from "@editframe/api/pipelines/upload";
await uploadFragmented(client, "dashcam.mp4", {
onCreated: async (file) => {
await createPipelineRun(client, { pipeline_id: pipelineId, file_id: file.id }, { idempotencyKey: `upload:${file.id}` });
},
});
パイプラインの Webhook トピックについては、webhooks スキルを参照してください。
パイプラインを一時停止する
新しい作業を停止し、実行履歴を保持するには、パイプラインを一時停止します。一時停止はパイプラインのすべてのバージョンに適用されます。
import { pausePipeline, resumePipeline } from "@editframe/api/pipelines";
const paused = await pausePipeline(client, pipelineId); // paused.paused_at is the time of the pause.
await resumePipeline(client, pipelineId); // paused_at is null again.
- 一時停止中のパイプラインでも、新しいバージョン、実行、グループを受け付けます。新しい実行は
pendingのままになります。 - パイプラインを再開するまで、実行、ステップ、試行、セグメントウィンドウは開始されません。
- 一時停止前に開始した試行は続行されます。Editframe はそれらのエンドポイントコールバックとレビュー判断を記録します。
- 開始されなかったステップには期限が設定されないため、一時停止によってタイムアウトが発生することはありません。
- 実行をキャンセルして再試行できます。再試行された実行は、パイプラインを再開するまで
pendingのままになります。 - パイプラインを再開すると、待機中の実行とステップがすぐに開始されます。
- 2 回目の一時停止や再開を行っても、状態は変わらず、記録も残りません。アーカイブ済みのパイプラインは
409 pipeline_archivedを返します。 - Editframe は、各一時停止と再開を、実行した API キーまたはユーザーとともに記録します。この変更履歴はダッシュボードに表示されます。
- 一時停止と再開では、ウェブフックは送信されません。開始されなかった実行では、使用量も記録されません。
listPipelines(client, { paused: true })は、一時停止中のパイプラインのみを返します。
パイプライン CLI
editframe pipelines はクラウド API を直接呼び出します。API キーは EDITFRAME_TOKEN から読み取ります。--project、--bridge、その他のランタイムオプションは使用しません。
export EDITFRAME_TOKEN="$EDITFRAME_API_KEY"
npx editframe pipelines create speech-check --definition speech-check.json
npx editframe pipelines runs create PIPELINE_ID FILE_ID --watch
npx editframe pipelines upload dashcam.mp4 --run PIPELINE_ID --watch
npx editframe pipelines reviews approve REVIEW_ID --patch corrections.json
npx editframe pipelines pause PIPELINE_ID
npx editframe pipelines resume PIPELINE_ID
--watchは、実行が失敗またはキャンセルされた場合、終了ステータス 1 で終了します。--jsonは、API レスポンスを JSON 形式で出力します。- すべてのコマンドについては、
npx editframe pipelines --helpを実行してください。
フィードバックを送信する
問題や改善点について、Editframe にフィードバックを送信します。
- Editframe または Editframe のスキルが問題を引き起こした場合は、回避策を見つけてタスクを続行してください。その後、問題と回避策を報告します。
- 現在のタスクだけでなく、ほかのタスクにも役立つ改善点を見つけた場合は、提案を送信してください。たとえば、より明確な指示、不足している例、より適切なデフォルト、新機能を提案できます。
問題や提案が異なる場合は、それぞれ個別に報告してください。報告に失敗しても、タスクを続行してください。
const headers: Record<string, string> = { "Content-Type": "application/json" };
if (process.env.EDITFRAME_API_KEY) headers.Authorization = `Bearer ${process.env.EDITFRAME_API_KEY}`;
const response = await fetch("https://editframe.com/api/v1/feedback", {
method: "POST",
headers,
body: JSON.stringify({
category: "feature_request",
skill: "editframe-api",
summary: "Add a function that cancels a render",
details: "A render started with the wrong input. No function stops it, so the render uses time and quota.",
workaround: "I let the render finish and ignored the output.",
context: { render_id: render.id, package: "@editframe/api" },
}),
});
本文は application/json として送信します。
| フィールド | 必須 | 上限 | 内容 |
|---|---|---|---|
category | はい | — | 以下のカテゴリのいずれか |
summary | はい | 200 文字 | 問題または提案の内容を示す 1 行の説明 |
details | はい | 10,000 文字 | 問題の場合:手順、期待される結果、実際の結果、エラーメッセージ。提案の場合:変更内容とそのメリット。 |
workaround | いいえ | 10,000 文字 | 問題に対して使用した回避策 |
skill | いいえ | 100 文字 | 使用したスキル。例:composition |
context | いいえ | 20 件 | 文字列値のみ。例:render_id、file_id、パッケージのバージョン。キーは 1~64 文字です。値は最大 1,000 文字です。 |
| カテゴリ | 用途 |
|---|---|
bug | Editframe がドキュメントの説明どおりに動作しない場合。 |
documentation | スキルまたはドキュメントに誤りがある、不明瞭である、または不完全な場合。 |
feature_request | 必要な機能が Editframe にない場合。 |
performance | 処理が遅い、またはリソースを使いすぎる場合。 |
other | ワークフローや API の設計に関する内容など、その他すべての問題や提案。 |
リクエスト本文の上限は 256 KiB です。不明なフィールドがあるとエラーになります。
Authorization ヘッダーは省略可能です。有効な API キーを指定した報告では、組織が特定されます。キーを指定しない報告は匿名になります。報告にシークレット、API キー、個人データを含めないでください。
| ステータス | 本文 | 対応 |
|---|---|---|
201 | { "id", "created_at" } | 対応は不要です。Editframe が報告を受け取りました。 |
400 | { "error": "invalid_json" | "invalid_feedback", "message" } | message に従って報告を修正し、再送信してください。 |
401 | Unauthorized | API キーが無効です。Authorization ヘッダーを付けずに、報告を再送信してください。 |
413 | { "error": "payload_too_large", "message" } | 報告を短くしてください。 |
415 | { "error": "unsupported_media_type", "message" } | Content-Type: application/json を設定してください。 |
429 | { "error": "rate_limited", "message" } | Retry-After の間隔が経過するまで、追加の報告を送信しないでください。 |
503 | { "error": "unavailable", "message" } | Retry-After の間隔が経過してから、報告をもう一度送信してください。 |
関数一覧
キャプションファイル
createCaptionFile(client: Client, payload: CreateCaptionFilePayload)— キャプションファイルを作成しますlookupCaptionFileByMd5(client: Client, md5: string)uploadCaptionFile(client: Client, fileId: string, fileStream: ReadableStream, fileSize: number)
ファイル
createFile(client: Client, payload: CreateFilePayload)createFileTrack(client: Client, fileId: string, payload: CreateISOBMFFTrackPayload)deleteFile(client: Client, id: string)getFileDetail(client: Client, id: string)getFileProcessingProgress(client: Client, id: string)getFileTranscription(client: Client, id: string)lookupFileByMd5(client: Client, md5: string)transcribeFile(client: Client, id: string, options?: { trackId?: number })— 使用しないでください。このエンドポイントは 410 Gone を返します。ファイルを文字起こしするには、transcribeステップを含むパイプライン実行を開始してください。uploadFile(client: Client, uploadDetails: { id: string; byte_size: number; type: FileType }, fileStream: ReadableStream)uploadFileIndex(client: Client, fileId: string, fileStream: ReadableStream, fileSize: number)uploadFileTrack(client: Client, fileId: string, trackId: number, byteSize: number, fileStream: ReadableStream)
画像ファイル
createImageFile(client: Client, payload: CreateImageFilePayload)getImageFileMetadata(client: Client, id: string)lookupImageFileByMd5(client: Client, md5: string)uploadImageFile(client: Client, uploadDetails: { id: string; byte_size: number; }, fileStream: ReadableStream, chunkSizeBytes?: number)
ISOBMFF ファイル
createISOBMFFFile(client: Client, payload: CreateISOBMFFFilePayload)getISOBMFFFileTranscription(client: Client, id: string)lookupISOBMFFFileByMd5(client: Client, md5: string)transcribeISOBMFFFile(client: Client, id: string, payload?: TranscribeISOBMFFFilePayload)— 使用しないでください。このエンドポイントは 410 Gone を返します。ファイルを文字起こしするには、transcribeステップを含むパイプライン実行を開始してください。uploadFragmentIndex(client: Client, fileId: string, fileStream: ReadableStream, fileSize: number)
ISOBMFF トラック
createISOBMFFTrack(client: Client, payload: CreateISOBMFFTrackPayload)uploadISOBMFFTrack(client: Client, fileId: string, trackId: number, fileStream: ReadableStream, trackSize: number)
Node
createImageFileFromPath(client: Client, path: string)createUnprocessedFileFromPath(client: Client, path: string)upload(client: Client, filePath: string)uploadUnprocessedFile(client: Client, uploadDetails: UnprocessedFileUploadDetails, path: string)
ISOBMFF の処理
getIsobmffProcessInfo(client: Client, id: string)getIsobmffProcessProgress(client: Client, id: string)
レンダリング
createRender(client: Client, payload: CreateRenderPayload)defaultWorkSliceMs()deleteRender(client: Client, id: string)downloadRender(client: Client, id: string)getRenderInfo(client: Client, id: string)getRenderProgress(client: Client, id: string)lookupRenderByMd5(client: Client, md5: string)uploadRender(client: Client, renderId: string, fileStream: ReadableStream)
文字起こし
createTranscription(client: Client, payload: CreateTranscriptionPayload)— 使用しないでください。このエンドポイントは 410 Gone を返します。ファイルを文字起こしするには、transcribeステップを含むパイプライン実行を開始してください。getTranscriptionInfo(client: Client, id: string)getTranscriptionProgress(client: Client, id: string)
未処理ファイル
createUnprocessedFile(client: Client, payload: CreateUnprocessedFilePayload)lookupUnprocessedFileByMd5(client: Client, md5: string)processIsobmffFile(client: Client, id: string)uploadUnprocessedReadableStream(client: Client, uploadDetails: UnprocessedFileUploadDetails, fileStream: ReadableStream)
URL トークン
createURLToken(client: Client, url: string)
CLI コマンド
グローバルオプション:
| オプション | デフォルト | 説明 |
|---|---|---|
-h, --help | — | 使用方法を表示します |
--version | — | CLI のバージョンを表示します |
--project <value> | — | ローカルプロジェクトの絶対パス |
--bridge <value> | — | インストール済みのブリッジ実行ファイル |
--component <value> | — | インストール済みの署名済みコンポーネントディレクトリ |
--registry <value> | — | ローカルブリッジレジストリディレクトリ |
--editor <value> | — | 検証済みのエディターアセットディレクトリ |
--editor-version <value> | — | 検証済みのエディターバージョン |
--compiler-pack <value> | — | 検証済みのコンパイラパックファイル |
--compiler-pack-sha256 <value> | — | 期待されるコンパイラパックの SHA-256 |
--endpoint <value> | — | ホスト型ランタイム API エンドポイント |
--project-id <value> | — | ホスト型プロジェクト識別子 |
--composition <value> | — | コンポジション識別子 |
--input <value> | — | 明示的な操作識別子とリビジョンを含む JSON リクエストファイル |
--job <value> | — | ジョブ識別子 |
-o, --output <value> | — | render が書き込む MP4 ファイル(デフォルトは output.mp4) |
| コマンド | 目的 |
|---|---|
editframe command | 明示的なリビジョン付きコンポジションコマンドを適用します |
editframe compositions | 選択したプロジェクト内のコンポジションを一覧表示します |
editframe context | コンポジションのリビジョンと編集コンテキストを読み取ります |
editframe export | 選択したコンポジションのエクスポートをリクエストします |
editframe job | プロジェクトのジョブを 1 件読み取ります |
editframe jobs | プロジェクトのジョブを一覧表示します |
editframe mcp | MCP stdio 経由でエージェントをローカルブリッジに接続します |
editframe open | ローカルのブラウザーエディターを開きます |
editframe pipelines | クラウドパイプライン、実行、グループ、レビューを管理します |
editframe projects | アクセス可能なプロジェクトを一覧表示します |
editframe render | ローカルランタイムとヘッドレス Chrome を使用してコンポジションを MP4 にレンダリングします |
editframe start | プロジェクト用にインストール済みのローカルブリッジを起動します |
editframe status | ローカルブリッジのステータスを表示します |
editframe stop | プロジェクトのローカルブリッジを停止します |