公式SDKは、サーバーコードやスクリプトから使えるようREST APIをラップしています。1回の呼び出しでファイルを文字起こしします。録音をアップロードし、ジョブの完了を待ち、文字起こし結果を返します。その間にSDKは、分数が確保される前にファイルを検査し、安全に再試行できる処理を再試行し、長いアップロードを維持し、すべてのアップロードと購入に冪等キーを付けるため、再試行しても二重に課金されることはありません。CLIはTypeScript SDKをベースにしており、ターミナルから同じ操作ができます。
パッケージ
| 言語 | パッケージ | レジストリ | ソース |
|---|---|---|---|
| TypeScript | @hushscript/sdk | npm: www.npmjs.com/package/@hushscript/sdk | github.com/Hushscript/hushscript-sdk-typescript |
| Python | hushscript | PyPI: pypi.org/project/hushscript | github.com/Hushscript/hushscript-sdk-python |
| Go | github.com/Hushscript/hushscript-sdk-go | pkg.go.dev: pkg.go.dev/github.com/Hushscript/hushscript-sdk-go | github.com/Hushscript/hushscript-sdk-go |
| PHP | hushscript/sdk | Packagist: packagist.org/packages/hushscript/sdk | github.com/Hushscript/hushscript-sdk-php |
| CLI | @hushscript/cli | npm: www.npmjs.com/package/@hushscript/cli | github.com/Hushscript/hushscript-cli |
必要なランタイムのバージョン:
- TypeScript: Node 22以上。Bun 1.2以上とDeno 2以上は、パッケージのインポートのみ確認しており、HTTPの動作は対象外です。
- Python: 3.10以上。
- Go: 1.25以上。
- PHP: 8.2以上。
ext-jsonとext-mbstringが必要です。パートの同時アップロードにはext-curlも必要です。 - CLI: Node 22以上。
SDKはサーバーとスクリプト向けです。APIはブラウザのオリジンを受け付けません。ブラウザ向けバンドルにトークンを入れると、そのトークンが漏えいします。そのためTypeScript SDKは、windowとdocumentが存在する環境では起動を拒否します。
トークンの取得
すべてのSDKとCLIは、パーソナルアクセストークンで認証します。アカウント内のMCPページの新しいトークンを作成から発行し、コードに必要なスコープを選び、分数の購入を許可するかどうかを決めます。トークンは一度だけ表示され、hsr1:<region>:pat.<id>.<secret>の形式です。スコープとトークンの仕組みはAPIのページで説明しています。
トークンを渡さない場合、SDKはHUSHSCRIPT_TOKENから読み取ります。
export HUSHSCRIPT_TOKEN=hsr1:...
エージェントは、自分のアカウントを開設し、ホスト型のチェックアウトページで支払いを済ませ、最初のトークンをコードから取得することもできます。TypeScriptではHushscript.agent.signup()とHushscript.agent.claim()、PythonではHushscript.agent_signup()とHushscript.agent_claim()、GoではAgentSignupとAgentClaim、PHPではClient::agentSignup()とClient::agentClaim()を使います。流れとルールは自動文字起こしで説明しています。
TypeScript
npm install @hushscript/sdk
import { writeFile } from "node:fs/promises";
import { Hushscript } from "@hushscript/sdk";
const hs = new Hushscript(); // reads HUSHSCRIPT_TOKEN
const transcript = await hs.transcribe("meeting.mp3");
console.log(transcript.text);
await writeFile("meeting.srt", transcript.toSRT());
transcribe()には、パス、Blob、Uint8Array、ReadableStream<Uint8Array>を渡せます。ストリームには、正確なsizeとdurationSecondsが必要です。hs.balance()は利用できる分数を返し、hs.transcripts.list()は完了した文字起こしをページ単位で取得し、hs.buy("300min", { acknowledgeNoRefund: true })はパックを購入します。/v1のすべての操作はhs.apiとしても利用でき、再試行、タイムアウト、秘匿化は同じです。
Python
pip install hushscript
from pathlib import Path
from hushscript import Hushscript
with Hushscript() as hs: # reads HUSHSCRIPT_TOKEN
transcript = hs.transcribe("meeting.mp3")
print(transcript.text)
Path("meeting.srt").write_text(transcript.to_srt(), encoding="utf-8")
すべての呼び出しには、同じ名前のasyncio版がAsyncHushscriptに用意されています。transcribe()には、パス、bytes、バイナリのファイルオブジェクトを渡せます。シークできないファイルオブジェクトにはsizeとduration_secondsが必要です。残高、文字起こしの一覧、購入には、それぞれhs.balance()、hs.transcripts.list()、hs.buy("300min", acknowledge_no_refund=True)を使います。
Go
go get github.com/Hushscript/hushscript-sdk-go
package main
import (
"context"
"fmt"
"log"
"os"
hushscript "github.com/Hushscript/hushscript-sdk-go"
)
func main() {
client, err := hushscript.New() // reads HUSHSCRIPT_TOKEN
if err != nil {
log.Fatal(err)
}
transcript, err := client.Transcribe(context.Background(), "meeting.mp3", nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(transcript.Text(nil))
if err := os.WriteFile("meeting.srt", []byte(transcript.SRT(nil)), 0o600); err != nil {
log.Fatal(err)
}
}
Transcribeはパスを受け取ります。TranscribeReaderはio.ReaderAtとその正確なサイズを、TranscribeStreamは前方にのみ読めるリーダーと、そのサイズおよびDurationSecondsを受け取ります。残高、文字起こしの一覧、購入には、それぞれclient.Balance、client.Transcripts.List、client.Buyを使います。オン、オフ、未設定を区別できるオプションは*boolで、hushscript.Boolで作成します。
PHP
composer require hushscript/sdk
<?php
require __DIR__ . '/vendor/autoload.php';
use Hushscript\Client;
$hs = new Client(); // reads HUSHSCRIPT_TOKEN
$transcript = $hs->transcribe('meeting.mp3');
echo $transcript->text();
file_put_contents('meeting.srt', $transcript->toSrt());
transcribe()には、パスまたは開いたストリームを渡せます。シークできないストリームには、sizeとduration_secondsオプションが必要です。オプションにはsnake_caseの配列キーを使い、結果はcamelCaseのプロパティで返ります。残高、文字起こしの一覧、購入には、それぞれ$hs->balance()、$hs->transcripts()->list()、$hs->buy('300min', true)を使います。Laravelでは、サービスプロバイダーでClientを1つバインドし、固定のidempotency_keyオプションを付けてキュー済みジョブ内で文字起こしを実行してください。
CLI
npm install --global @hushscript/cli
hushscript login
hushscript transcribe meeting.mp3 --format srt --out meeting.srt
CLIは、--token、HUSHSCRIPT_TOKEN、hushscript loginで保存されたトークンの順にトークンを探します。loginは入力を画面に表示せずにトークンを受け取り、ユーザー本人だけが読めるファイルに保存します。hushscript logoutで削除できます。CIでは環境変数の利用をおすすめします。
| コマンド | 内容 |
|---|---|
login |
トークンの入力を求めて保存します。 |
logout |
保存したトークンを削除します。 |
balance |
利用できる分数を表示します。 |
transcribe <file> |
録音をアップロードし、完了を待って文字起こし結果を出力します。フラグ: --language、--translate、--format srt|vtt|txt|json、--out、--key。 |
resume <token> <file> |
transcribeが途中で終わった文字起こしを完了させます。 |
transcripts |
完了した文字起こしを新しい順に一覧表示します。 |
transcript <id> |
文字起こしを1件出力します。 |
jobs |
ジョブを一覧表示します。--activeで未完了のジョブのみ表示します。 |
packs |
購入できる分数パックを価格とともに一覧表示します。 |
buy <pack> |
保存済みの既定のカードでパックを購入します。フラグ: --yes、--key。 |
--jsonを指定すると、標準出力にJSONドキュメントを1つだけ出力し、標準エラー出力はJSON Linesになります。終了コードは、成功が0、APIまたはSDKがエラーを報告した場合が1、使い方の誤り(何も送信されていない)が2、実行が中断された場合が130です。
対応ファイル
MP3、M4A、MP4、MOV(動画は音声トラックを使用)、WAV、FLAC、VorbisまたはOpusのOGGで、長さは15秒から10時間です。SDKはファイルのバイト列から形式を確認し、分数が確保される前に長さを調べます。メディアの変換は行わないため、それ以外の形式は先に変換してください。
ffmpeg -i input -vn -c:a libopus output.opus
エラー
SDKが発生させるエラーはすべて1つの系統に属するため、1つのcatchですべてを処理できます。TypeScriptとPythonではHushscriptError、Goでは*hushscript.Error、PHPではHushscriptExceptionです。エラーには、insufficient_balanceのようなスラッグ形式のcode、数値コード、HTTPステータス、メッセージ、次に何をすべきかを示すhint、詳細、retryAfter(PHPではスラッグがerrorCode、PythonではretryAfterがretry_after)が含まれます。
import { HushscriptError, InsufficientBalanceError } from "@hushscript/sdk";
try {
await hs.transcribe("meeting.mp3");
} catch (error) {
if (error instanceof InsufficientBalanceError) console.log(error.hint);
else if (error instanceof HushscriptError) console.log(error.code, error.hint ?? error.message);
else throw error;
}
PreflightErrorは、クレジットが確保される前にSDKがファイルを拒否したことを意味します。残高がファイルに足りるかどうかはサーバーが判断します。アップロードの作成時、パートが1つも送信される前に402が返されます。
課金と再試行
すべてのアップロードと購入には冪等キーが付き、再試行でも同じキーが使われます。そのため、再試行した呼び出しは2回目を開始せず、最初の呼び出しの結果を再生します。
buy()は、保存済みの既定のカードに課金します。コードからの購入は、3つの設定がすべて有効になるまでオフです。トークンにbillingスコープがあること、トークンで「このトークンに分数の購入を許可」がオンになっていること、アカウントで「連携済みアプリの分数購入を許可」がオンになっていることです。1つでも欠けていると、呼び出しはpat_scope_missingで失敗します。呼び出す前に、返金不可の通知を購入者に表示してください。
購入の再試行は、ネットワークエラー、502、503の場合に、同じキーで最大1回です。何も課金されていないことが確実な応答もあります。400、402、404、422と、コード4021(pat_purchase_requires_app、カードが拒否された、またはユーザーの操作なしには課金できない)または4023(pat_purchase_requires_authentication、銀行が支払いの確認を求めている)の403です。4021または4023の後は、アプリでパックを購入してください。リクエストの送信後に起きたそれ以外の失敗は、401や429も含め、カードに課金された可能性があります。そのエラーには冪等キーが含まれます。同じキーでもう一度実行すれば、購入が二重に行われることはありません。Pythonの例です。
from hushscript import HushscriptError
try:
purchase = hs.buy("300min", acknowledge_no_refund=True)
except HushscriptError as error:
refused = error.status in {400, 402, 404, 422} or (
error.status == 403 and error.numeric_code in {4021, 4023}
)
if error.idempotency_key is None or refused:
raise # only these refusals charged nothing; any other failure keeps the key for a retry
purchase = hs.buy("300min", acknowledge_no_refund=True, idempotency_key=error.idempotency_key)
リクエストの送信前に失敗した購入にはキーが付いておらず、何も課金されていません。自分で渡すキーは、A-Za-z0-9_-の1〜128文字にしてください。別のパックに同じキーを再利用しないでください。購入リクエストが送信された可能性がある場合、CLIはキーを出力します。
hushscript buy 300min --yes --key <key>
再開トークン
ジョブが作成された後は、エラーに冪等キーと並んで再開トークンが含まれます。待機がタイムアウトすると、トークン付きのWaitTimeoutErrorが発生しますが、ジョブは実行され続けます。トークンをresume()に渡せば、二重に課金されることなく処理を続行できます。アップロードを終えたジョブにはファイルは不要で、アップロード中のジョブは同じファイルで続行します。PHPの例です。
try {
$hs->transcribe($path, ['wait_timeout' => 60]);
} catch (\Hushscript\Exception\WaitTimeoutError $timeout) {
$transcript = $hs->resume($timeout->resumeToken, $path);
}
CLIでは、transcribeの実行中にCtrl-Cを押すと、ジョブの再開トークンと、続行するためのコマンドが表示されます。
hushscript resume <token> meeting.mp3 --format srt --out meeting.srt
ログと秘匿化
SDKはテレメトリーを送信しません。クライアントを識別する情報はUser-Agentヘッダーだけです。ログは既定でオフです。HUSHSCRIPT_LOG=debugを指定すると、リクエストごとに、メソッド、パス、ステータス、所要時間を1行で標準エラー出力に書き込みます。ヘッダー、本文、タイトル、文字起こしのテキストは書き込まれません。
トークンは、すべてのエラー、ログ行、クライアントの出力表示から秘匿化されます。エラーメッセージ、ヒント、原因では、URLのホストとパスは残り、クエリ文字列は?[redacted]になるため、署名付きアップロードURLが出力されることはありません。クレームシークレットや新しいトークンのように秘密の値を返す結果では、フィールドとしては読み取れますが、出力表示では[redacted]になります。JSONエクスポートはご自身のデータなので、値がそのまま含まれます。CLIは、把握しているすべてのトークンを標準エラー出力から除去します。標準出力の結果はご自身の出力であり、除去されません。
設定
| 設定 | 環境変数 | 既定値 |
|---|---|---|
| トークン | HUSHSCRIPT_TOKEN |
なし |
| ベースURL | HUSHSCRIPT_BASE_URL |
https://api.hushscript.com |
| ログレベル | HUSHSCRIPT_LOG |
off |
| リクエストのタイムアウト | なし | 60秒 |
| 再試行 | なし | 3回 |
コードで渡したオプションは環境変数より優先され、空の値は未設定として扱われます。分数はアプリと同じ残高から使われます。パックと価格は料金ページをご覧ください。