apick-api 1.1.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +44 -3
- package/docs/guide.en.md +22 -2
- package/docs/guide.ko.md +22 -2
- package/package.json +2 -2
- package/src/index.cjs +67 -16
- package/src/index.d.ts +23 -1
- package/src/index.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0 - 2026-09-01
|
|
4
|
+
|
|
5
|
+
- `downloadTtsSubtitles(jobId)`로 발화 타이밍 ASS 자막을 별도 1회 다운로드할 수 있습니다.
|
|
6
|
+
- TTS 상태 타입에 `subtitles_available`을 추가했습니다.
|
|
7
|
+
- 허용 IP 공란, 단일 IPv4·CIDR 등록, 즉시 반영 규칙을 한영 문서에 추가했습니다.
|
|
8
|
+
|
|
9
|
+
## 2.0.1 - 2026-08-31
|
|
10
|
+
|
|
11
|
+
- TTS 작업 취소 범위를 `waiting`과 `processing` 상태로 확장했습니다.
|
|
12
|
+
- 실행 중 취소도 접수 시 과금된 금액을 환불하지 않는 계약을 한영 문서에 반영했습니다.
|
|
13
|
+
- 17개 TTS `voice_id`의 사용자 표시 이름을 공개 문서에 추가했습니다.
|
|
14
|
+
|
|
15
|
+
## 2.0.0 - 2026-08-30
|
|
16
|
+
|
|
17
|
+
- 종료된 동기 `textToSpeech()` 계약을 제거했습니다.
|
|
18
|
+
- `createTtsJob()`, `getTtsJob()`, `cancelTtsJob()`, `downloadTtsResult()`로 비동기 한국어 TTS Jobs 계약을 제공합니다.
|
|
19
|
+
- 지원 목소리, 최대 800자, 상태 조회, 대기 중 취소, 결과 MP3(`audio/mpeg`) 1회 다운로드를 문서화했습니다.
|
|
20
|
+
- 정식 게시 전 지원 목소리를 17개 중립 내레이션 음성으로 확장하고 `TTS_VOICE_IDS`를 추가했습니다.
|
|
21
|
+
|
|
3
22
|
## 1.1.1 - 2026-08-30
|
|
4
23
|
|
|
5
24
|
- 공개된 25개 API 계약에 종료 대상 이미지 생성 기능이 포함되지 않았음을 재검증했습니다.
|
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# APICK API for Node.js
|
|
4
4
|
|
|
5
|
-
**에이픽 주요 API
|
|
5
|
+
**에이픽 주요 API 25개를 API 키 하나로 간편하게 호출하는 공식 Node.js SDK**
|
|
6
6
|
|
|
7
|
-
**Official zero-dependency Node.js SDK for
|
|
7
|
+
**Official zero-dependency Node.js SDK for 25 popular APICK Korean data and AI APIs**
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/apick-api)
|
|
10
10
|
[](https://nodejs.org/)
|
|
@@ -45,6 +45,9 @@ console.log(result.data);
|
|
|
45
45
|
인증키는 [apick.app](https://apick.app) 가입 후 마이페이지에서 발급할 수 있습니다.
|
|
46
46
|
Get an API key from your account page after signing up at [apick.app](https://apick.app).
|
|
47
47
|
|
|
48
|
+
마이페이지의 허용 IP가 공란이면 제한 없이 호출할 수 있습니다. 제한하려면 APICK에 도착하는 공인 IPv4를 단일 주소 또는 CIDR(`/32` 등)로 등록하세요. 저장 즉시 반영되며 별도 동기화는 필요하지 않습니다.
|
|
49
|
+
Leave the allowed-IP list blank for unrestricted access. To restrict access, register the public IPv4 address seen by APICK as an exact address or CIDR such as `/32`. Changes apply immediately with no separate synchronization.
|
|
50
|
+
|
|
48
51
|
## 제공 서비스 / Included services
|
|
49
52
|
|
|
50
53
|
| Method | APICK service | Result |
|
|
@@ -64,7 +67,11 @@ Get an API key from your account page after signing up at [apick.app](https://ap
|
|
|
64
67
|
| `googleSearch(keyword, options)` | 웹 검색 / Web search | JSON |
|
|
65
68
|
| `googleImageSearch(keyword, options)` | 이미지 검색 / Image search | JSON |
|
|
66
69
|
| `screenshot(url)` | 웹페이지 화면캡처 / Web screenshot | Binary |
|
|
67
|
-
| `
|
|
70
|
+
| `createTtsJob(text, options)` | 한국어 내레이션 작업 접수 / Create TTS job | JSON |
|
|
71
|
+
| `getTtsJob(jobId)` | TTS 작업 상태 / TTS job status | JSON |
|
|
72
|
+
| `cancelTtsJob(jobId)` | 대기·생성 중 TTS 작업 취소 / Cancel waiting or processing TTS job | JSON |
|
|
73
|
+
| `downloadTtsResult(jobId)` | TTS 결과 1회 다운로드 / One-time TTS result | MP3 |
|
|
74
|
+
| `downloadTtsSubtitles(jobId)` | TTS 자막 1회 다운로드 / One-time TTS subtitles | ASS |
|
|
68
75
|
| `htmlToPdf(html, options)` | HTML→PDF | Binary |
|
|
69
76
|
| `jsonToExcel(data, options)` | JSON→Excel | Binary |
|
|
70
77
|
| `summarize(text)` | 텍스트 요약 / Text summarization | JSON |
|
|
@@ -127,6 +134,40 @@ await excel.save('./scores.xlsx');
|
|
|
127
134
|
|
|
128
135
|
`ApickBinaryResult` provides `bytes`, `size`, `filename`, `contentType`, `meta`, `toArrayBuffer()`, `toBlob()`, and `save(path)`.
|
|
129
136
|
|
|
137
|
+
## 비동기 TTS Jobs / Asynchronous TTS Jobs
|
|
138
|
+
|
|
139
|
+
기존 동기 TTS는 종료되었습니다. 한국어 내레이션은 작업을 접수하고 `completed`가 될 때까지 2~5초 간격으로 상태를 확인한 뒤 MP3 결과를 한 번만 내려받습니다.
|
|
140
|
+
|
|
141
|
+
The legacy synchronous TTS API has retired. Create a Korean narration job, poll every 2–5 seconds until it is `completed`, then download the MP3 result once.
|
|
142
|
+
|
|
143
|
+
17 neutral narration voices are supported: the five original `narrator_m_01`–`narrator_m_05` voices plus `narrator_f_10s_01`–`03`, `narrator_m_20s_01`, `narrator_f_20s_01`–`04`, `narrator_m_30s_01`–`02`, `narrator_m_40s_01`, and `narrator_m_80s_01`. Import `TTS_VOICE_IDS` for the exact list.
|
|
144
|
+
|
|
145
|
+
표시 이름 / voice labels: `narrator_m_01` 태준, `narrator_m_02` 민석, `narrator_m_03` 도현, `narrator_m_04` 강우, `narrator_m_05` 성훈, `narrator_f_10s_01` 서아, `narrator_f_10s_02` 하린, `narrator_f_10s_03` 예린, `narrator_m_20s_01` 도윤, `narrator_f_20s_01` 지안, `narrator_f_20s_02` 서윤, `narrator_f_20s_03` 소연, `narrator_f_20s_04` 유나, `narrator_m_30s_01` 현우, `narrator_m_30s_02` 준혁, `narrator_m_40s_01` 정우, `narrator_m_80s_01` 영수.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
const created = await apick.createTtsJob('오늘의 이야기를 시작합니다.', {
|
|
149
|
+
voiceId: 'narrator_m_03'
|
|
150
|
+
});
|
|
151
|
+
const jobId = created.data.job_id;
|
|
152
|
+
|
|
153
|
+
let job;
|
|
154
|
+
do {
|
|
155
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
156
|
+
job = await apick.getTtsJob(jobId);
|
|
157
|
+
} while (job.data.status === 'waiting' || job.data.status === 'processing');
|
|
158
|
+
|
|
159
|
+
if (job.data.status === 'completed') {
|
|
160
|
+
const result = await apick.downloadTtsResult(jobId);
|
|
161
|
+
await result.save(`./${jobId}.mp3`);
|
|
162
|
+
const subtitles = await apick.downloadTtsSubtitles(jobId);
|
|
163
|
+
await subtitles.save(`./${jobId}.ass`);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
접수 성공 시 과금되며 취소해도 환불되지 않습니다. 취소는 `waiting` 또는 `processing` 상태에서 가능하고, MP3와 ASS 자막은 각각 한 번만 내려받을 수 있습니다. 각 다운로드가 시작되면 해당 서버 원본이 즉시 폐기되므로 전송 중단 시에도 다시 받을 수 없습니다.
|
|
168
|
+
|
|
169
|
+
The charge is final when the job is accepted. Cancellation is allowed while `waiting` or `processing`. The MP3 and ASS subtitles can each be downloaded once. Starting either download immediately consumes that server copy, so an interrupted transfer cannot be downloaded again.
|
|
170
|
+
|
|
130
171
|
## 신분증 마스킹 / Identity masking
|
|
131
172
|
|
|
132
173
|
```js
|
package/docs/guide.en.md
CHANGED
|
@@ -19,6 +19,8 @@ const client = new ApickClient({
|
|
|
19
19
|
|
|
20
20
|
Pass the API key only to the constructor. The SDK does not keep it in enumerable client properties and never prints it in logs or error messages.
|
|
21
21
|
|
|
22
|
+
Leave the allowed-IP list blank for unrestricted access. To restrict access, register the public IPv4 address seen by APICK as an exact address or CIDR such as `/32`. Changes apply immediately with no separate synchronization.
|
|
23
|
+
|
|
22
24
|
## Business, validation, and addresses
|
|
23
25
|
|
|
24
26
|
```js
|
|
@@ -76,12 +78,30 @@ await client.ocr(bytes, {
|
|
|
76
78
|
|
|
77
79
|
## Generated files
|
|
78
80
|
|
|
81
|
+
TTS supports 17 neutral narration `voice_id` values: five original narrators and twelve new voices. Import `TTS_VOICE_IDS` for the exact list.
|
|
82
|
+
|
|
83
|
+
Voice labels: `narrator_m_01` 태준, `narrator_m_02` 민석, `narrator_m_03` 도현, `narrator_m_04` 강우, `narrator_m_05` 성훈, `narrator_f_10s_01` 서아, `narrator_f_10s_02` 하린, `narrator_f_10s_03` 예린, `narrator_m_20s_01` 도윤, `narrator_f_20s_01` 지안, `narrator_f_20s_02` 서윤, `narrator_f_20s_03` 소연, `narrator_f_20s_04` 유나, `narrator_m_30s_01` 현우, `narrator_m_30s_02` 준혁, `narrator_m_40s_01` 정우, `narrator_m_80s_01` 영수.
|
|
84
|
+
|
|
79
85
|
```js
|
|
80
86
|
const screenshot = await client.screenshot('https://example.com');
|
|
81
87
|
await screenshot.save('./example.jpeg');
|
|
82
88
|
|
|
83
|
-
const
|
|
84
|
-
|
|
89
|
+
const created = await client.createTtsJob('오늘의 이야기를 시작합니다.', { voiceId: 'narrator_m_03' });
|
|
90
|
+
const jobId = created.data.job_id;
|
|
91
|
+
let job = await client.getTtsJob(jobId);
|
|
92
|
+
while (job.data.status === 'waiting' || job.data.status === 'processing') {
|
|
93
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
94
|
+
job = await client.getTtsJob(jobId);
|
|
95
|
+
}
|
|
96
|
+
if (job.data.status === 'completed') {
|
|
97
|
+
const result = await client.downloadTtsResult(jobId);
|
|
98
|
+
await result.save(`./${jobId}.mp3`); // audio/mpeg; downloadable once
|
|
99
|
+
const subtitles = await client.downloadTtsSubtitles(jobId);
|
|
100
|
+
await subtitles.save(`./${jobId}.ass`); // ASS subtitles; separately downloadable once
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Cancellation is available while waiting or processing and does not refund the accepted charge.
|
|
104
|
+
// MP3 and ASS downloads each consume their server copy immediately and cannot be repeated.
|
|
85
105
|
|
|
86
106
|
const pdf = await client.htmlToPdf('<h1>Report</h1>', { pagination: true });
|
|
87
107
|
await pdf.save('./report.pdf');
|
package/docs/guide.ko.md
CHANGED
|
@@ -19,6 +19,8 @@ const client = new ApickClient({
|
|
|
19
19
|
|
|
20
20
|
인증키는 생성자에만 전달하세요. 클라이언트 객체의 열거 가능한 속성에 저장되지 않으며 SDK가 로그로 출력하지 않습니다.
|
|
21
21
|
|
|
22
|
+
마이페이지의 허용 IP가 공란이면 제한 없이 호출할 수 있습니다. 제한하려면 APICK에 도착하는 공인 IPv4를 단일 주소 또는 CIDR(`/32` 등)로 등록하세요. 저장 즉시 반영되며 별도 동기화는 필요하지 않습니다.
|
|
23
|
+
|
|
22
24
|
## 조회와 검증
|
|
23
25
|
|
|
24
26
|
```js
|
|
@@ -76,12 +78,30 @@ await client.ocr(bytes, {
|
|
|
76
78
|
|
|
77
79
|
## 파일 생성
|
|
78
80
|
|
|
81
|
+
TTS는 기존 남성 내레이터 5개와 신규 중립 내레이션 12개를 합쳐 17개 `voice_id`를 지원합니다. 정확한 목록은 `TTS_VOICE_IDS` 상수로 확인할 수 있습니다.
|
|
82
|
+
|
|
83
|
+
표시 이름: `narrator_m_01` 태준, `narrator_m_02` 민석, `narrator_m_03` 도현, `narrator_m_04` 강우, `narrator_m_05` 성훈, `narrator_f_10s_01` 서아, `narrator_f_10s_02` 하린, `narrator_f_10s_03` 예린, `narrator_m_20s_01` 도윤, `narrator_f_20s_01` 지안, `narrator_f_20s_02` 서윤, `narrator_f_20s_03` 소연, `narrator_f_20s_04` 유나, `narrator_m_30s_01` 현우, `narrator_m_30s_02` 준혁, `narrator_m_40s_01` 정우, `narrator_m_80s_01` 영수.
|
|
84
|
+
|
|
79
85
|
```js
|
|
80
86
|
const screenshot = await client.screenshot('https://example.com');
|
|
81
87
|
await screenshot.save('./example.jpeg');
|
|
82
88
|
|
|
83
|
-
const
|
|
84
|
-
|
|
89
|
+
const created = await client.createTtsJob('오늘의 이야기를 시작합니다.', { voiceId: 'narrator_m_03' });
|
|
90
|
+
const jobId = created.data.job_id;
|
|
91
|
+
let job = await client.getTtsJob(jobId);
|
|
92
|
+
while (job.data.status === 'waiting' || job.data.status === 'processing') {
|
|
93
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
94
|
+
job = await client.getTtsJob(jobId);
|
|
95
|
+
}
|
|
96
|
+
if (job.data.status === 'completed') {
|
|
97
|
+
const result = await client.downloadTtsResult(jobId);
|
|
98
|
+
await result.save(`./${jobId}.mp3`); // audio/mpeg, 1회만 다운로드 가능
|
|
99
|
+
const subtitles = await client.downloadTtsSubtitles(jobId);
|
|
100
|
+
await subtitles.save(`./${jobId}.ass`); // ASS 자막, 별도 1회 다운로드
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 취소는 waiting 또는 processing 상태에서 가능하며 이미 과금된 금액은 환불되지 않습니다.
|
|
104
|
+
// MP3와 ASS는 각각 다운로드 시작 시 해당 서버 원본이 즉시 폐기되어 재다운로드할 수 없습니다.
|
|
85
105
|
|
|
86
106
|
const pdf = await client.htmlToPdf('<h1>보고서</h1>', { pagination: true });
|
|
87
107
|
await pdf.save('./report.pdf');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apick-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Official zero-dependency Node.js client for 25 APICK APIs. 에이픽 주요 API 25개를 간편하게 호출하는 공식 Node.js SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.cjs",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"google-search",
|
|
65
65
|
"pdf",
|
|
66
66
|
"excel",
|
|
67
|
-
"tts",
|
|
67
|
+
"tts-jobs",
|
|
68
68
|
"text-summary"
|
|
69
69
|
]
|
|
70
70
|
}
|
package/src/index.cjs
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
const DEFAULT_BASE_URL = 'https://apick.app';
|
|
4
4
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
5
5
|
const MAX_OCR_BYTES = 50 * 1024 * 1024;
|
|
6
|
+
const TTS_VOICE_IDS = Object.freeze([
|
|
7
|
+
'narrator_m_01', 'narrator_m_02', 'narrator_m_03', 'narrator_m_04', 'narrator_m_05',
|
|
8
|
+
'narrator_f_10s_01', 'narrator_f_10s_02', 'narrator_f_10s_03',
|
|
9
|
+
'narrator_m_20s_01', 'narrator_f_20s_01', 'narrator_f_20s_02',
|
|
10
|
+
'narrator_f_20s_03', 'narrator_f_20s_04', 'narrator_m_30s_01',
|
|
11
|
+
'narrator_m_30s_02', 'narrator_m_40s_01', 'narrator_m_80s_01'
|
|
12
|
+
]);
|
|
13
|
+
const TTS_VOICE_ID_SET = new Set(TTS_VOICE_IDS);
|
|
6
14
|
|
|
7
15
|
const SERVICE_DEFINITIONS = Object.freeze({
|
|
8
16
|
businessDetails: { endpoint: '/rest/biz_detail', timeoutMs: 50_000, output: 'json' },
|
|
@@ -25,7 +33,7 @@ const SERVICE_DEFINITIONS = Object.freeze({
|
|
|
25
33
|
googleSearch: { endpoint: '/rest/google_search', timeoutMs: 35_000, output: 'json' },
|
|
26
34
|
googleImageSearch: { endpoint: '/rest/google_image_search', timeoutMs: 35_000, output: 'json' },
|
|
27
35
|
screenshot: { endpoint: '/rest/url_screenshot', timeoutMs: 75_000, output: 'binary', filename: 'screenshot.jpeg' },
|
|
28
|
-
|
|
36
|
+
createTtsJob: { endpoint: '/rest/tts/jobs', timeoutMs: 35_000, output: 'json' },
|
|
29
37
|
htmlToPdf: { endpoint: '/rest/html_to_pdf', timeoutMs: 25_000, output: 'binary', filename: 'document.pdf' },
|
|
30
38
|
jsonToExcel: { endpoint: '/rest/json_to_excel', timeoutMs: 45_000, output: 'binary', filename: 'data.xlsx' },
|
|
31
39
|
summarize: { endpoint: '/rest/llm/text_summary', timeoutMs: 75_000, output: 'json' },
|
|
@@ -87,6 +95,18 @@ function normalizeUrl(value) {
|
|
|
87
95
|
return parsed.toString();
|
|
88
96
|
}
|
|
89
97
|
|
|
98
|
+
function normalizeTtsJobId(value) {
|
|
99
|
+
const jobId = requiredString('jobId', value);
|
|
100
|
+
if (!/^[a-f0-9]{32}$/.test(jobId)) throw new TypeError('jobId must be a 32-character lowercase hexadecimal string.');
|
|
101
|
+
return jobId;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function normalizeTtsVoice(value) {
|
|
105
|
+
const voiceId = requiredString('voiceId', value);
|
|
106
|
+
if (!TTS_VOICE_ID_SET.has(voiceId)) throw new RangeError('voiceId must be one of the supported TTS voice IDs.');
|
|
107
|
+
return voiceId;
|
|
108
|
+
}
|
|
109
|
+
|
|
90
110
|
function numberOrNull(value) {
|
|
91
111
|
if (value === undefined || value === null || value === '') return null;
|
|
92
112
|
const number = Number(value);
|
|
@@ -252,9 +272,10 @@ class ApickClient {
|
|
|
252
272
|
: positiveInteger('timeoutMs', options.timeoutMs);
|
|
253
273
|
}
|
|
254
274
|
|
|
255
|
-
async _call(serviceName, payload, formData) {
|
|
256
|
-
const
|
|
257
|
-
if (!
|
|
275
|
+
async _call(serviceName, payload, formData, requestOptions) {
|
|
276
|
+
const baseDefinition = SERVICE_DEFINITIONS[serviceName];
|
|
277
|
+
if (!baseDefinition) throw new TypeError(`Unknown APICK service: ${serviceName}`);
|
|
278
|
+
const definition = Object.assign({}, baseDefinition, requestOptions || {});
|
|
258
279
|
|
|
259
280
|
const controller = new AbortController();
|
|
260
281
|
const timeoutMs = this.#timeoutMs || definition.timeoutMs || DEFAULT_TIMEOUT_MS;
|
|
@@ -263,14 +284,17 @@ class ApickClient {
|
|
|
263
284
|
Accept: definition.output === 'binary' ? '*/*' : 'application/json',
|
|
264
285
|
CL_AUTH_KEY: this.#apiKey
|
|
265
286
|
};
|
|
287
|
+
const method = definition.method || 'POST';
|
|
266
288
|
const request = {
|
|
267
|
-
method
|
|
289
|
+
method,
|
|
268
290
|
headers,
|
|
269
|
-
body: formData || JSON.stringify(payload || {}),
|
|
270
291
|
signal: controller.signal,
|
|
271
292
|
redirect: 'error'
|
|
272
293
|
};
|
|
273
|
-
if (
|
|
294
|
+
if (method !== 'GET') {
|
|
295
|
+
request.body = formData || JSON.stringify(payload || {});
|
|
296
|
+
if (!formData) headers['Content-Type'] = 'application/json';
|
|
297
|
+
}
|
|
274
298
|
|
|
275
299
|
let response;
|
|
276
300
|
try {
|
|
@@ -318,7 +342,7 @@ class ApickClient {
|
|
|
318
342
|
throw new ApickApiError(failureMessage, {
|
|
319
343
|
status: response.status,
|
|
320
344
|
code: response.status === 401 ? 'APICK_AUTH_ERROR' : 'APICK_API_ERROR',
|
|
321
|
-
serviceCode: body && body.data && typeof body.data.error_code === 'string' ? body.data.error_code : undefined
|
|
345
|
+
serviceCode: body && body.data && typeof (body.data.code || body.data.error_code) === 'string' ? (body.data.code || body.data.error_code) : undefined
|
|
322
346
|
});
|
|
323
347
|
}
|
|
324
348
|
|
|
@@ -437,15 +461,41 @@ class ApickClient {
|
|
|
437
461
|
return this._call('screenshot', { url: normalizeUrl(url) });
|
|
438
462
|
}
|
|
439
463
|
|
|
440
|
-
|
|
464
|
+
createTtsJob(text, options) {
|
|
441
465
|
const config = options || {};
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
466
|
+
return this._call('createTtsJob', {
|
|
467
|
+
voice_id: normalizeTtsVoice(config.voiceId || 'narrator_m_03'),
|
|
468
|
+
text: requiredString('text', text, 800)
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
getTtsJob(jobId) {
|
|
473
|
+
const id = normalizeTtsJobId(jobId);
|
|
474
|
+
return this._call('createTtsJob', null, null, { endpoint: '/rest/tts/jobs/' + id, method: 'GET' });
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
cancelTtsJob(jobId) {
|
|
478
|
+
const id = normalizeTtsJobId(jobId);
|
|
479
|
+
return this._call('createTtsJob', null, null, { endpoint: '/rest/tts/jobs/' + id + '/cancel' });
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
downloadTtsResult(jobId) {
|
|
483
|
+
const id = normalizeTtsJobId(jobId);
|
|
484
|
+
return this._call('createTtsJob', null, null, {
|
|
485
|
+
endpoint: '/rest/tts/jobs/' + id + '/result',
|
|
486
|
+
method: 'GET',
|
|
487
|
+
output: 'binary',
|
|
488
|
+
filename: id + '.mp3'
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
downloadTtsSubtitles(jobId) {
|
|
493
|
+
const id = normalizeTtsJobId(jobId);
|
|
494
|
+
return this._call('createTtsJob', null, null, {
|
|
495
|
+
endpoint: '/rest/tts/jobs/' + id + '/subtitles',
|
|
496
|
+
method: 'GET',
|
|
497
|
+
output: 'binary',
|
|
498
|
+
filename: id + '.ass'
|
|
449
499
|
});
|
|
450
500
|
}
|
|
451
501
|
|
|
@@ -479,5 +529,6 @@ module.exports = {
|
|
|
479
529
|
ApickApiError,
|
|
480
530
|
ApickBinaryResult,
|
|
481
531
|
SERVICES,
|
|
532
|
+
TTS_VOICE_IDS,
|
|
482
533
|
DEFAULT_BASE_URL
|
|
483
534
|
};
|
package/src/index.d.ts
CHANGED
|
@@ -31,6 +31,24 @@ export interface MaskResidentNumberOptions extends OcrOptions {
|
|
|
31
31
|
type: 1 | 2 | 3;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
export const TTS_VOICE_IDS: readonly [
|
|
35
|
+
'narrator_m_01', 'narrator_m_02', 'narrator_m_03', 'narrator_m_04', 'narrator_m_05',
|
|
36
|
+
'narrator_f_10s_01', 'narrator_f_10s_02', 'narrator_f_10s_03',
|
|
37
|
+
'narrator_m_20s_01', 'narrator_f_20s_01', 'narrator_f_20s_02',
|
|
38
|
+
'narrator_f_20s_03', 'narrator_f_20s_04', 'narrator_m_30s_01',
|
|
39
|
+
'narrator_m_30s_02', 'narrator_m_40s_01', 'narrator_m_80s_01'
|
|
40
|
+
];
|
|
41
|
+
export type TtsVoiceId = typeof TTS_VOICE_IDS[number];
|
|
42
|
+
|
|
43
|
+
export interface TtsJobData {
|
|
44
|
+
job_id: string;
|
|
45
|
+
status: 'waiting' | 'processing' | 'completed' | 'cancelled' | 'failed';
|
|
46
|
+
voice_id?: TtsVoiceId;
|
|
47
|
+
character_count?: number;
|
|
48
|
+
result_available?: boolean;
|
|
49
|
+
subtitles_available?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
34
52
|
export class ApickApiError extends Error {
|
|
35
53
|
readonly status: number;
|
|
36
54
|
readonly code: string;
|
|
@@ -84,7 +102,11 @@ export class ApickClient {
|
|
|
84
102
|
googleSearch(keyword: string, options?: { page?: number }): Promise<ApickResult>;
|
|
85
103
|
googleImageSearch(keyword: string, options?: { page?: number }): Promise<ApickResult>;
|
|
86
104
|
screenshot(url: string): Promise<ApickBinaryResult>;
|
|
87
|
-
|
|
105
|
+
createTtsJob(text: string, options?: { voiceId?: TtsVoiceId }): Promise<ApickResult<TtsJobData>>;
|
|
106
|
+
getTtsJob(jobId: string): Promise<ApickResult<TtsJobData>>;
|
|
107
|
+
cancelTtsJob(jobId: string): Promise<ApickResult<TtsJobData>>;
|
|
108
|
+
downloadTtsResult(jobId: string): Promise<ApickBinaryResult>;
|
|
109
|
+
downloadTtsSubtitles(jobId: string): Promise<ApickBinaryResult>;
|
|
88
110
|
htmlToPdf(html: string, options?: { pagination?: boolean }): Promise<ApickBinaryResult>;
|
|
89
111
|
jsonToExcel(data: unknown[], options?: { sheetName?: string }): Promise<ApickBinaryResult>;
|
|
90
112
|
summarize(text: string): Promise<ApickResult>;
|