SRT字幕のタイミングをミリ秒単位でずらします
各字幕の内部形式が正しくても、字幕全体が常に早すぎたり遅すぎたりすることがあります。このツールは、符号付きのミリ秒値を使ってSRTファイル全体の時刻を一括で移動します。字幕本文や並び順は変更しません。正の値では表示が遅くなり、負の値では早くなります。移動後に負になるタイムスタンプはゼロへ補正されます。番号付きの各ブロックを検証し、不正な時刻があれば、壊れた字幕ファイルを返さずエラーとしてお知らせします。
無料で実行
信頼できる同期ポイントから移動量を決めます
まず動画の冒頭付近で、ドアが閉まる瞬間、話し始め、タイトルの表示など、判定しやすい出来事を探してください。その出来事と対応する字幕を比較し、差をミリ秒で測ります。字幕が出来事より先に表示される場合は、正の値を指定して遅らせます。後から表示される場合は、負の値を指定して早めます。全体へ適用する前に、番組の終盤でも同じ確認を行ってください。差が最後まで一定なら、単一の移動量で正しく補正できます。差が時間とともに広がる場合は、再生速度のずれやフレームレート変換が原因と考えられ、一定値の移動だけでは直せません。完全なSRTテキストと符号付き整数を送信してください。結果では番号と字幕行を保持し、有効な開始時刻と終了時刻だけを置き換えます。元ファイルを上書きせず、新しい`.srt`ファイルとして保存し、制作環境へ反映する前に両方を比較することをおすすめします。
入力検証とゼロ補正の動作を確認します
各SRTブロックには、数字のインデックス、時刻行、1行以上の字幕本文が必要です。時刻は標準の`時:分:秒,ミリ秒`形式を使用します。時は2桁以上、分と秒はそれぞれ2桁、ミリ秒はちょうど3桁で記述し、分と秒はゼロから五十九の範囲にしてください。時刻行がこの構造に合わない場合、どちらかのタイムスタンプが不正な場合、または元の終了時刻が開始時刻より前の場合、そのブロックを拒否します。厳密に検証するため、一部だけ変換され、壊れた字幕が出力内に残ることはありません。負の移動量は開始と終了へ個別に適用されます。計算結果がゼロ未満なら、正確に`00:00:00,000`へ補正します。そのため、大きく前へ移動すると、冒頭のブロックが開始も終了もゼロになり、長さがなくなる場合があります。これは計算ミスではなく仕様です。大幅に早めた後は、最初の字幕を必ずご確認ください。
移動後のファイルを安全に運用します
正しい動画との確認が終わるまで元の字幕を保管し、結果は別名で保存してください。冒頭の1か所だけで判断せず、会話、音楽、場面転換を動画内の複数箇所で確認します。この処理が変更するのはタイムスタンプだけです。本文の翻訳、番号の振り直し、誤字の修正、欠落字幕の推測、時間とともに増えるずれの補正は行いません。字幕本文内の改行は維持されるため、複数行の表示構成も保たれます。出力では改行形式とブロック間隔を統一し、一般的なSRT対応ソフトで扱える形に整えます。アルゴリズムは決定的で、ネットワーク、乱数、モデルを使用しないため、同じ入力と移動量からは常に同じ結果が得られます。ブラウザー上で実行するほか、1リクエストあたり$0.002でAPIから自動化できます。一括処理では、使用した移動量と動画の版を一緒に記録してください。別編集版に前置きや広告が追加されると、同じ補正値が合わないことがあります。
活用例
一定の音声遅延を補正します
多重化や再生設定によって字幕が発話より先に出る場合、すべての字幕を後ろへ移動します。
削除された導入部分を調整します
固定長のリーダー、カウントダウン、タイトル映像を削除した後、全ブロックを前へ移動します。
納品用ファイルを統一します
測定済みの編集補正を適用し、公開用パッケージを作る前に一貫したSRT時刻を得られます。
よくある質問
正と負のどちらを指定すればよいですか?
字幕を遅く表示する場合は正の値、早く表示する場合は負の値をご指定ください。
移動後の時刻がゼロ未満になるとどうなりますか?
該当する開始または終了時刻を`00:00:00,000`へ補正し、負の時刻は出力しません。
字幕のドリフトも修正できますか?
できません。一定の移動は一定の差だけを直します。差が広がる場合は、速度またはフレーム時刻の補正が必要です。
字幕本文や番号は変わりますか?
変わりません。番号と本文行を保持し、時刻だけを置換します。改行形式とブロック間隔は統一されます。
不正な時刻を含むブロックがある場合はどうなりますか?
対象ブロックを示す入力エラーで処理全体が失敗します。部分的に移動したファイルは返しません。
APIリクエストの料金はいくらですか?
APIは1リクエストあたり$0.002です。同じ決定的な処理をブラウザーでもご利用いただけます。
開発者向け — APIアクセス
このページの機能はすべてAPIからも利用できます。自社システムに組み込みたいチーム向けのセクションです。それ以外の方は上のツールをそのままお使いください。
エンドポイント
Bearerトークンで認証し、POST1回でタスクをキューに登録します。結果はWebhookまたは署名付きリンクで受け取れます。
お使いのスタックから呼び出す
curl -X POST https://api.kit.forhosting.com/video/subtitle-srt-shift \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"srt":"1\n00:00:01,250 --> 00:00:03,500\nOpening line.\n\n2\n00:00:05,000 --> 00:00:07,250\nSecond line.","offset_ms":-1500}'const res = await fetch("https://api.kit.forhosting.com/video/subtitle-srt-shift", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"srt": "1\n00:00:01,250 --> 00:00:03,500\nOpening line.\n\n2\n00:00:05,000 --> 00:00:07,250\nSecond line.",
"offset_ms": -1500
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/subtitle-srt-shift",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"srt": "1\n00:00:01,250 --> 00:00:03,500\nOpening line.\n\n2\n00:00:05,000 --> 00:00:07,250\nSecond line.",
"offset_ms": -1500
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/subtitle-srt-shift", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"srt":"1\\n00:00:01,250 --> 00:00:03,500\\nOpening line.\\n\\n2\\n00:00:05,000 --> 00:00:07,250\\nSecond line.","offset_ms":-1500}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"srt":"1\n00:00:01,250 --> 00:00:03,500\nOpening line.\n\n2\n00:00:05,000 --> 00:00:07,250\nSecond line.","offset_ms":-1500}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/subtitle-srt-shift", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)リクエスト例
{
"srt": "1\n00:00:01,250 --> 00:00:03,500\nOpening line.\n\n2\n00:00:05,000 --> 00:00:07,250\nSecond line.",
"offset_ms": -1500
}レスポンス例
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.subtitle_srt_shift",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}非同期APIです。task_idは即時に返ります。ポーリングは1秒あたり1リクエストまでです。
料金
単価はすべて公開しています。トークン換算や独自クレジットはありません。失敗したタスクは課金されません。
制限
max_mb | 500 |
max_minutes | 60 |
max_megapixels | 3.9 |
エラー
| HTTP | コード | 意味 |
|---|---|---|
401 | unauthorized | APIキーが無効か、指定されていません。Authorizationヘッダーを確認してください。 |
402 | insufficient_balance | 残高が不足しています。チャージ後に再度お試しください。 |
404 | unknown_type | 指定されたタスクタイプは存在しません。タイプ名を確認してください。 |
429 | rate_limited | リクエストが多すぎます。しばらく待ってから再度お試しください。 |