Chuyển đến nội dung chính

Nhà phát triển

SDK và CLI của Hushscript

Thư viện chính thức cho TypeScript, Python, Go và PHP, cùng một công cụ dòng lệnh, biến file đã ghi thành bản phiên âm chỉ với một lệnh gọi.

Các SDK chính thức bao quanh REST API cho mã phía máy chủ và script. Một lệnh gọi là phiên âm được một file: SDK tải bản ghi lên, chờ job hoàn tất rồi trả về bản phiên âm. Ở giữa, SDK kiểm tra file trước khi giữ bất kỳ phút nào, thử lại những gì an toàn để thử lại, giữ cho lượt tải lên dài không bị ngắt, và gắn idempotency key vào mọi lượt tải lên và mua hàng để việc thử lại không bao giờ tính phí hai lần. CLI được xây trên SDK TypeScript và làm điều tương tự từ terminal.

Gói

Ngôn ngữ Gói Registry Mã nguồn
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

Phiên bản runtime tối thiểu:

SDK dành cho máy chủ và script. API không chấp nhận origin của trình duyệt, và token trong bundle trình duyệt là token đã bị lộ, nên SDK TypeScript từ chối khởi động ở nơi có window và document.

Lấy token

Mọi SDK và CLI đều xác thực bằng token truy cập cá nhân. Hãy tạo token trong mục Tạo token mới trên trang MCP trong tài khoản, chọn scope mà mã của bạn cần và quyết định liệu token có được mua phút hay không. Token chỉ hiển thị một lần và có dạng hsr1:<region>:pat.<id>.<secret>. Các scope và cách token hoạt động nằm trên trang API.

SDK đọc token từ HUSHSCRIPT_TOKEN khi bạn không truyền token:

export HUSHSCRIPT_TOKEN=hsr1:...

Một agent cũng có thể tự mở tài khoản, thanh toán tại trang checkout được lưu trữ và nhận token đầu tiên từ mã: Hushscript.agent.signup() và Hushscript.agent.claim() trong TypeScript, Hushscript.agent_signup() và Hushscript.agent_claim() trong Python, AgentSignup và AgentClaim trong Go, còn Client::agentSignup() và Client::agentClaim() trong PHP. Quy trình và các quy tắc của nó nằm trong Sử dụng tự động.

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() nhận một đường dẫn, Blob, Uint8Array hoặc ReadableStream<Uint8Array>. Stream cần size và durationSeconds chính xác. hs.balance() trả về số phút bạn có thể dùng, hs.transcripts.list() duyệt từng trang các bản phiên âm đã hoàn tất, và hs.buy("300min", { acknowledgeNoRefund: true }) mua một gói. Mọi thao tác /v1 cũng có sẵn dưới dạng hs.api, với cùng cơ chế thử lại, timeout và che thông tin nhạy cảm.

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")

Mỗi lệnh gọi đều có bản asyncio tương ứng trên AsyncHushscript với cùng tên. transcribe() nhận một đường dẫn, bytes hoặc đối tượng file nhị phân; đối tượng file không thể seek cần size và duration_seconds. hs.balance(), hs.transcripts.list() và hs.buy("300min", acknowledge_no_refund=True) lần lượt xử lý số dư, danh sách bản phiên âm và việc mua gói.

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 nhận một đường dẫn, TranscribeReader nhận một io.ReaderAt cùng kích thước chính xác của nó, còn TranscribeStream nhận một reader chỉ đọc tiến cùng kích thước và DurationSeconds. client.Balance, client.Transcripts.List và client.Buy lần lượt xử lý số dư, danh sách bản phiên âm và việc mua gói. Các tùy chọn có thể tắt, bật hoặc chưa đặt là *bool, được tạo bằng 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() nhận một đường dẫn hoặc một stream đang mở; stream không thể seek cần các tùy chọn size và duration_seconds. Tùy chọn dùng khóa mảng snake_case, còn kết quả dùng thuộc tính camelCase. $hs->balance(), $hs->transcripts()->list() và $hs->buy('300min', true) lần lượt xử lý số dư, danh sách bản phiên âm và việc mua gói. Với Laravel, hãy bind một Client trong service provider và chạy việc phiên âm trong queued job với tùy chọn idempotency_key cố định.

CLI

npm install --global @hushscript/cli
hushscript login
hushscript transcribe meeting.mp3 --format srt --out meeting.srt

CLI lấy token từ --token, rồi đến HUSHSCRIPT_TOKEN, rồi đến token mà hushscript login đã lưu. login hỏi token mà không hiển thị khi nhập và lưu trong một file mà chỉ người dùng của bạn đọc được; hushscript logout xóa file đó. Trong CI, nên dùng biến môi trường.

Lệnh Tác dụng
login Hỏi token và lưu lại.
logout Xóa token đã lưu.
balance Hiển thị số phút bạn có thể dùng.
transcribe <file> Tải bản ghi lên, chờ và in bản phiên âm. Cờ: --language, --translate, --format srt|vtt|txt|json, --out, --key.
resume <token> <file> Hoàn tất lượt phiên âm mà transcribe để dở.
transcripts Liệt kê các bản phiên âm đã hoàn tất, mới nhất trước.
transcript <id> In một bản phiên âm.
jobs Liệt kê job; dùng --active cho những job chưa hoàn tất.
packs Liệt kê các gói phút bạn có thể mua, kèm giá.
buy <pack> Mua một gói bằng thẻ mặc định đã lưu của bạn. Cờ: --yes, --key.

--json in đúng một tài liệu JSON ra stdout và không gì khác, đồng thời biến stderr thành JSON Lines. Mã thoát là 0 khi thành công, 1 khi API hoặc SDK báo lỗi, 2 khi dùng sai cú pháp (chưa gửi gì), và 130 khi lượt chạy bị ngắt.

Định dạng file được hỗ trợ

MP3, M4A, MP4 và MOV (dùng track âm thanh của video), WAV, FLAC và OGG với Vorbis hoặc Opus, từ 15 giây đến 10 giờ. SDK kiểm tra định dạng từ các byte của file và đo thời lượng trước khi giữ bất kỳ phút nào. SDK không chuyển đổi media, nên hãy chuyển đổi mọi định dạng khác trước:

ffmpeg -i input -vn -c:a libopus output.opus

Lỗi

Mọi lỗi mà SDK phát ra đều thuộc một họ, nên một catch là đủ cho tất cả: HushscriptError trong TypeScript và Python, *hushscript.Error trong Go và HushscriptException trong PHP. Một lỗi mang theo code dạng slug như insufficient_balance, mã số, trạng thái HTTP, thông báo, một hint cho biết nên làm gì tiếp theo, phần chi tiết và retryAfter (trong PHP slug là errorCode; trong Python retryAfter là 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 nghĩa là SDK đã từ chối file trước khi giữ bất kỳ khoản tín dụng nào. Số dư của bạn có đủ cho một file hay không là do máy chủ quyết định: mã 402 được trả về khi lượt tải lên được tạo, trước khi gửi bất kỳ phần nào.

Tính phí và thử lại

Mọi lượt tải lên và mọi lượt mua đều mang một idempotency key, và các lần thử lại dùng lại key đó, nên lệnh gọi được thử lại sẽ phát lại lệnh đầu tiên thay vì bắt đầu lệnh thứ hai.

buy() tính phí thẻ mặc định đã lưu của bạn. Việc mua từ mã bị tắt cho đến khi ba công tắc cho phép: token có scope billing, token bật “Cho phép token này mua phút”, và “Cho phép ứng dụng đã kết nối mua phút” được bật cho tài khoản. Nếu thiếu bất kỳ công tắc nào, lệnh gọi thất bại với pat_scope_missing. Hãy hiển thị cho người mua thông báo không hoàn tiền trước khi bạn gọi lệnh này.

Một lượt mua được thử lại tối đa một lần, khi gặp lỗi mạng, 502 hoặc 503, với cùng key. Một số phản hồi chứng minh rằng chưa có khoản nào bị tính phí: 400, 402, 404 hoặc 422, và 403 với mã 4021 (pat_purchase_requires_app, thẻ bị từ chối hoặc không thể tính phí nếu thiếu bạn) hoặc 4023 (pat_purchase_requires_authentication, ngân hàng muốn xác nhận khoản thanh toán). Sau 4021 hoặc 4023, hãy mua gói trong ứng dụng. Mọi lỗi khác sau khi yêu cầu đã được gửi, kể cả 401 hoặc 429, nghĩa là thẻ có thể đã bị tính phí. Lỗi đó mang theo idempotency key: hãy gọi lại với cùng key, và lượt mua không bao giờ xảy ra hai lần. Trong 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)

Lượt mua thất bại trước khi yêu cầu được gửi sẽ không mang key: không có gì bị tính phí. Key do bạn tự truyền phải dài từ 1 đến 128 ký tự thuộc A-Za-z0-9_-; đừng dùng lại cho một gói khác. CLI in key khi một lượt mua có thể đã được gửi:

hushscript buy 300min --yes --key <key>

Resume token

Khi job đã tồn tại, lỗi mang theo một resume token bên cạnh idempotency key. Một lượt chờ hết thời gian sẽ phát ra WaitTimeoutError kèm token, và job vẫn tiếp tục chạy. Hãy truyền token trở lại resume() để đi tiếp mà không bị tính phí lần hai: job đã qua bước tải lên không cần file, còn job đang tải lên dở sẽ được tiếp tục với cùng file. Trong PHP:

try {
    $hs->transcribe($path, ['wait_timeout' => 60]);
} catch (\Hushscript\Exception\WaitTimeoutError $timeout) {
    $transcript = $hs->resume($timeout->resumeToken, $path);
}

Trong CLI, nhấn Ctrl-C khi transcribe đang chạy sẽ in resume token của job và lệnh để tiếp tục:

hushscript resume <token> meeting.mp3 --format srt --out meeting.srt

Ghi log và che thông tin nhạy cảm

SDK không gửi telemetry; header User-Agent là định danh client duy nhất. Ghi log mặc định tắt. HUSHSCRIPT_LOG=debug ghi một dòng cho mỗi yêu cầu ra standard error với method, path, trạng thái và thời gian, và không bao giờ ghi header, body, tiêu đề hay nội dung bản phiên âm.

Token bị che khỏi mọi lỗi, dòng log và dạng in ra của client. Trong thông báo lỗi, hint và nguyên nhân, URL giữ nguyên host và path nhưng query string trở thành ?[redacted], nên URL tải lên đã ký không bao giờ bị in ra. Các kết quả trao cho bạn một bí mật, chẳng hạn bí mật xác nhận hoặc token mới, vẫn giữ giá trị đọc được dưới dạng trường nhưng hiện [redacted] khi in; bản xuất JSON là của riêng bạn và mang theo giá trị đó. CLI xóa mọi token nó biết khỏi stderr; kết quả của nó trên stdout là đầu ra của bạn và không bị xóa.

Cấu hình

Thiết lập Biến môi trường Mặc định
Token HUSHSCRIPT_TOKEN không có
URL gốc HUSHSCRIPT_BASE_URL https://api.hushscript.com
Mức log HUSHSCRIPT_LOG off
Timeout yêu cầu không có 60 giây
Số lần thử lại không có 3

Tùy chọn truyền trong mã được ưu tiên hơn biến môi trường của nó, và giá trị rỗng được coi là chưa đặt. Số phút lấy từ cùng số dư với ứng dụng; các gói và giá nằm trên trang giá.

Bắt đầu chuyển thành văn bản với 30 phút dùng thử

Xem trước tối đa 5 phút trước khi bạn tạo tài khoản, và tài khoản cá nhân mới được xem trước miễn phí file đầu tiên tải lên trong ứng dụng. Chuyển toàn bộ bản ghi thành văn bản cần có tài khoản và số phút; tài khoản cá nhân đủ điều kiện nhận 30 phút miễn phí một lần, sau khi xác minh thẻ hoặc cùng lần mua đầu tiên. Không subscription.

Bắt đầu với 30 phút miễn phí