Created
June 20, 2021 06:04
-
-
Save hmmhmmhm/b8628ebe3a360e75221484b10045525f to your computer and use it in GitHub Desktop.
네이버 클로바 TTS API 자바스크립트 & 타입스크립트 사용법 (Naver Clova TTS API Javascript & Typescript Usage)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import axios from 'axios' | |
import path from 'path' | |
import fs from 'fs' | |
import querystring from 'qs' | |
import { Readable } from 'stream' | |
export const Speakers = [ | |
/** | |
* 다인 (여아 목소리) | |
*/ | |
'ndain', | |
/** | |
* 하준 (남아 목소리) | |
*/ | |
'nhajun', | |
/** | |
* 아라 (여성 목소리, 하이톤) | |
*/ | |
'dara_ang', | |
/** | |
* 민서 (여성 목소리, 차분) | |
*/ | |
'nminseo', | |
/** | |
* 종현 (남성 목소리, 하이톤) | |
*/ | |
'njonghyun', | |
/** | |
* 준영 (남성 목소리, 차분) | |
*/ | |
'njoonyoung', | |
] as const | |
export type SpeakerType = typeof Speakers[number] | |
export interface ITTS { | |
speaker: SpeakerType | |
/** | |
* -5에서 5 사이의 정수 값이며, | |
* -5 이면 0.5 배 낮은 볼륨이고 | |
* 5 이면 1.5 배 더 큰 볼륨입니다. | |
* 0 이면 정상 볼륨의 목소리로 음성을 합성합니다. | |
*/ | |
volume: number | |
/** | |
* -5에서 5 사이의 정수 값이며, | |
* -5 이면 2 배 빠른 속도이고 | |
* 5 이면 0.5 배 더 느린 속도입니다. | |
* 0 이면 정상 속도의 목소리로 음성을 합성합니다. | |
*/ | |
speed: number | |
/** | |
* -5에서 5 사이의 정수 값이며, | |
* -5 이면 1.2 배 높은 피치이고 | |
* 5 이면 0.8 배 더 낮은 피치입니다. | |
* 0 이면 정상 피치의 목소리로 음성을 합성합니다. | |
*/ | |
pitch: number | |
text: string | |
format: 'mp3' | 'wav' | |
} | |
export const getTTSStream = (props: { | |
clientId: string | |
clientSecret: string | |
tts: ITTS | |
}) => { | |
return new Promise<Readable>(async (resolve, reject) => { | |
const apiUrl = 'https://naveropenapi.apigw.ntruss.com/tts-premium/v1/tts' | |
const response = await axios.post( | |
apiUrl, | |
querystring.stringify(props.tts), | |
{ | |
headers: { | |
'X-NCP-APIGW-API-KEY-ID': props.clientId, | |
'X-NCP-APIGW-API-KEY': props.clientSecret, | |
'Content-Type': 'application/x-www-form-urlencoded', | |
}, | |
responseType: 'stream', | |
} | |
) | |
if (response && response.data) { | |
const readableStream: Readable = response.data | |
resolve(readableStream) | |
} else { | |
reject() | |
} | |
}) | |
} | |
const main = async () => { | |
await new Promise(async (resolve, reject) => { | |
try { | |
const readableStream = await getTTSStream({ | |
clientId: `<CLINET ID>`, | |
clientSecret: `<CLIENT SECRET>`, | |
tts: { | |
format: 'mp3', | |
speaker: 'ndain', | |
pitch: 0, | |
speed: 0, | |
volume: 0, | |
text: `동해물과 백두산이 마르고 닳도록`, | |
}, | |
}) | |
readableStream.pipe( | |
fs.createWriteStream(path.join(process.cwd(), `blabla.mp3`)) | |
) | |
readableStream.once('end', resolve) | |
} catch (error) { | |
reject(error) | |
} | |
}) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment