# 1. upload the video once - YouTube, Drive, S3, Vimeo or direct URL
curl -X POST https://api.rask.ai/api/library/v1/media/link \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"link": "https://example.com/onboarding.mp4", "name": "onboarding"}'
# 2. one project per subtitle language
for lang in es-mx fr-fr ja-jp; do
curl -X POST https://api.rask.ai/v2/projects \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d "{\"video_id\": \"$VIDEO_ID\", \"dst_lang\": \"$lang\"}"
done# When status is merging_done, download both subtitle files
P=$(curl -s https://api.rask.ai/v2/projects/$ID -H "Authorization: Bearer $TOKEN")
curl -s -o onboarding.es-mx.srt "$(echo $P | jq -r .translation_srt_path)"
curl -s -o onboarding.es-mx.vtt "$(echo $P | jq -r .translation_vtt_path)"동영상을 파일로 전송하거나 YouTube, Google Drive, S3, Vimeo 또는 기타 직링크의 링크를 게시하세요. 한 번 업로드하면 모든 언어의 자막에 적용됩니다.
미디어 ID를 video_id로 전달하고 프로젝트당 하나의 목표 언어를 설정하세요. 서로 다른 언어의 프로젝트는 병렬로 처리됩니다.
상태가 merging_done에 도달할 때까지 확인한 다음, .srt 및 .vtt 파일을 다운로드하여 저장하세요.
# pip install git+ssh://[email protected]/braskai/rask-sdk.git@main
import asyncio, urllib.request
from rask_sdk import clients, enums, schemas
LANGS = ["es-mx", "fr-fr", "ja-jp"]
async def subtitle(client, video_id, lang):
job = await client.create_project(data=schemas.ProjectCreate(video_id=video_id, dst_lang=lang))
while job.status is not enums.ProjectStatus.MERGING_DONE:
await asyncio.sleep(10)
job = await client.get_project(project_id=job.id)
# links are presigned for one hour - save the files right away
urllib.request.urlretrieve(job.translation_srt_path, f"video.{lang}.srt")
urllib.request.urlretrieve(job.translation_vtt_path, f"video.{lang}.vtt")
async def main():
client = clients.RaskSDKClient(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
media = await client.create_media_link(data=schemas.MediaCreateLink(link="https://example.com/onboarding.mp4"))
while media.status is enums.MediaStatus.PROCESSING:
await asyncio.sleep(5)
media = await client.get_media(media_id=media.id)
await asyncio.gather(*(subtitle(client, media.id, l) for l in LANGS))
asyncio.run(main())import time, requests
AUTH = "https://rask-prod.auth.us-east-2.amazoncognito.com/oauth2/token"
API = "https://api.rask.ai"
token = requests.post(AUTH, auth=(CLIENT_ID, CLIENT_SECRET),
data={"grant_type": "client_credentials"}).json()["access_token"]
h = {"Authorization": f"Bearer {token}"}
pid = requests.post(f"{API}/v2/projects", headers=h,
json={"video_id": VIDEO_ID, "dst_lang": "de-de"}).json()["id"]
while (p := requests.get(f"{API}/v2/projects/{pid}", headers=h).json())["status"] != "merging_done":
time.sleep(10)
# translated subtitles: download the files
open("video.de-de.vtt", "wb").write(requests.get(p["translation_vtt_path"]).content)
# original-language captions: build a WebVTT file from the transcript segments
segs = requests.get(f"{API}/v2/projects/{pid}/transcription", headers=h).json()["segments"]
cues = [f"{s['start'].replace(',', '.')} --> {s['end'].replace(',', '.')}\n{s['src']['text']}" for s in segs]
open("video.en.vtt", "w").write("WEBVTT\n\n" + "\n\n".join(cues) + "\n")// no dependencies, Node 18+ global fetch
import { writeFile } from 'node:fs/promises';
const API = 'https://api.rask.ai';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const auth = await fetch('https://rask-prod.auth.us-east-2.amazoncognito.com/oauth2/token', {
method: 'POST',
headers: { Authorization: 'Basic ' + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`) },
body: new URLSearchParams({ grant_type: 'client_credentials' }),
}).then((r) => r.json());
const h = { Authorization: `Bearer ${auth.access_token}`, 'Content-Type': 'application/json' };
const call = (method, path, body) => fetch(API + path, { method, headers: h, body: body && JSON.stringify(body) }).then((r) => r.json());
const langs = ['es-mx', 'pt-br', 'ko-kr'];
const tracks = await Promise.all(langs.map(async (dst_lang) => {
let p = await call('POST', '/v2/projects', { video_id: VIDEO_ID, dst_lang });
while (p.status !== 'merging_done') { await sleep(10000); p = await call('GET', `/v2/projects/${p.id}`); }
const file = `subs/${dst_lang}.vtt`;
await writeFile(file, await ((await fetch(p.translation_vtt_path)).text()));
return `<track kind="subtitles" srclang="${dst_lang}" src="/${file}">`;
}));
console.log(tracks.join('\n')); // paste inside your <video> element# 1. token (valid 1 hour - cache and reuse it)
TOKEN=$(curl -s -X POST https://rask-prod.auth.us-east-2.amazoncognito.com/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" -d "grant_type=client_credentials" | jq -r .access_token)
# 2. create the project for one subtitle language
ID=$(curl -s -X POST https://api.rask.ai/v2/projects \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d "{\"video_id\": \"$VIDEO_ID\", \"dst_lang\": \"it-it\"}" | jq -r .id)
# 3. wait for merging_done
until [ "$(curl -s https://api.rask.ai/v2/projects/$ID -H "Authorization: Bearer $TOKEN" | jq -r .status)" = merging_done ]; do
sleep 10
done
# 4. save both subtitle files
P=$(curl -s https://api.rask.ai/v2/projects/$ID -H "Authorization: Bearer $TOKEN")
curl -s -o video.it-it.srt "$(echo $P | jq -r .translation_srt_path)"
curl -s -o video.it-it.vtt "$(echo $P | jq -r .translation_vtt_path)"<?php
use GuzzleHttp\Client;
$http = new Client(['base_uri' => 'https://api.rask.ai']);
$json = fn($r) => json_decode($r->getBody(), true);
$auth = $json((new Client)->post('https://rask-prod.auth.us-east-2.amazoncognito.com/oauth2/token',
['auth' => [$clientId, $clientSecret], 'form_params' => ['grant_type' => 'client_credentials']]));
$h = ['Authorization' => 'Bearer ' . $auth['access_token']];
foreach (['es-mx', 'tr-tr'] as $lang) {
$p = $json($http->post('/v2/projects', ['headers' => $h, 'json' => [
'video_id' => $videoId, 'dst_lang' => $lang]]));
while ($p['status'] !== 'merging_done') {
sleep(10);
$p = $json($http->get("/v2/projects/{$p['id']}", ['headers' => $h]));
}
// presigned links, valid for one hour
file_put_contents("video.$lang.srt", file_get_contents($p['translation_srt_path']));
file_put_contents("video.$lang.vtt", file_get_contents($p['translation_vtt_path']));
} 0s created
11s transcription_started
87s translation_started
99s voiceover_started
154s merging_started
165s merging_done

es-mx 및 es-es 모두 커버할 수 있습니다. 프로젝트 기록은 glossary_version유지되므로 나중에 수정하더라도 완료된 작업이 예기치 않게 변경되지 않습니다.네. 모든 Rask 프로젝트는 목표 언어로 된 SRT 및 WebVTT 자막 파일을 제공합니다. 영상을 업로드하고 자막 언어별로 프로젝트를 생성한 뒤, 프로젝트가 완료되면 파일을 다운로드하세요.
모든 프로젝트에 대해 목표 언어로 된 SRT 파일과 WebVTT(VTT) 파일, 두 가지 형식이 제공됩니다. 플랫폼에서 다른 자막 형식이 필요한 경우, 타임스탬프가 포함된 JSON 세그먼트 형식으로도 대본을 이용할 수 있습니다.
자막 파일은 목표 언어로 제공됩니다. 원본 언어 자막의 경우 대본 세그먼트를 확인하세요. 각 세그먼트에는 시작 및 종료 시간이 포함된 원본 텍스트가 있으므로 몇 줄의 코드로 SRT 또는 VTT 파일로 변환할 수 있습니다.
75개 원본 언어에서 es-mx, pt-br, fr-ca와 같은 지역별 옵션을 포함해 135개 이상의 언어로 자막을 이용할 수 있습니다. 프로젝트당 하나의 목표 언어가 지정되므로, 동일한 업로드 파일에서 언어별로 프로젝트를 각각 생성하세요.
아직 지원하지 않습니다. API는 플레이어이나 영상 편집 소프트웨어용 자막 파일을 제공합니다. 자막이 영상에 입혀진 결과물을 원하시면 Rask 웹 앱을 사용하세요.
파일에는 텍스트와 타이밍 정보가 포함됩니다. 글꼴, 크기, 색상, 위치는 동영상 플레이어, 앱 또는 편집 소프트웨어에서 설정하므로 하나의 자막 파일을 어디서든 유연하게 사용할 수 있습니다.
파일에는 대화 내용이 포함됩니다. 청각 장애인을 위한 음악 및 효과음 설명은 자동으로 생성되지 않으므로, 자막 편집 단계에서 직접 추가해 주세요.
각 자막 구간에는 SPEAKER_XX 형식의 화자 레이블이 표시되므로, 인터뷰나 대화 영상에 자막을 넣을 때 화자 이름을 직접 추가할 수 있습니다.
API를 통해 해당 구간의 텍스트나 타이밍을 수정한 후 프로젝트를 다시 생성하세요. 자막 파일은 더빙 버전과 함께 업데이트됩니다. 재작업 비용은 변경된 구간을 기준으로 청구되며, 실행당 최소 1분이 부과됩니다.
다운로드 링크는 보안을 위해 1시간 동안만 유효합니다. 파일은 개인 저장소에 미리 저장해 두시거나, 필요할 때 프로젝트를 다시 불러와 새로운 링크를 발급받으세요.
프로젝트 비용은 동영상 길이를 분 단위로 계산하며, 1분 미만은 올림 처리되어 Rask 앱과 동일한 크레딧에서 차감됩니다. 가격에는 오디오 변환, 번역, 자막 및 더빙 버전이 모두 포함되어 있습니다. 일반 요금제 사용 시 추가 시간은 분당 3달러가 부과되며, 기업용(Enterprise) 요금제는 계약 내용에 따라 맞춤형으로 제공됩니다.
API 이용은 Creator Pro, Business, Enterprise 요금제에서 제공되며, 사용 가능한 기능은 요금제에 따라 다릅니다. 앱에서 클라이언트 ID와 시크릿을 발급받으면 바로 연동을 시작할 수 있습니다. 기업용 계약, 대량 이용 할인, 맞춤형 언어 지원에 대해서는 당사 팀으로 문의해 주세요.