ボイスとオーディオ
Nodaro SDK を使って、TypeScript からボイスの参照、変更、差し替え、デザイン、動画の吹き替え、オーディオの分離、ミックス、文字起こしを行います。
client.voices は ElevenLabs のボイスを扱います。ボイスの一覧表示と検索、録音の声の変更、話者ごとの新しいボイスの割り当て、新しいボイスのデザイン、オーディオや動画の別の言語への吹き替えができます。client.audio は、オーディオの構成要素をそれぞれ単独で提供します。分離、声の抽出、エフェクト、ミックス、音量、結合、文字起こしです。どの生成メソッドも jobId を返すので、client.jobs.getStatus() でポーリングしてください。これらのメソッドは、音声とメディアの REST API を呼び出します。
メソッド
| メソッド | 内容 |
|---|---|
voices.list() | 標準ボイスを一覧表示します |
voices.searchLibrary(params?) | コミュニティのボイスライブラリを検索します |
voices.listClones() | 既存のボイスクローンを一覧表示します |
voices.deleteClone(id) | ボイスクローンの 1 つを削除します |
voices.createClone() と createCloneFromFile() | 廃止されました |
voices.change(input) | 録音や動画の声を差し替えます |
voices.recast(input) | 話者ごとに異なるボイスを割り当てます |
voices.analyze(input) | 差し替えの前に話者を検出します |
voices.exportMix(input) | ミックスしたボイスのステムから動画をレンダリングします |
voices.design(input) | 説明から新しいボイスを作成します |
voices.remix(input) | 説明したボイスでテキストを話します |
voices.dub(input) | オーディオや動画を別の言語に吹き替えます |
voices.textToDialogue(input) | 複数話者の脚本を 1 つのオーディオファイルとして音声にします |
audio.separate(input) | トラックをステムに分割します |
audio.isolate(input) | 主な声を残し、ノイズを取り除きます |
audio.applyFx(input) | リバーブ、エコー、電話、メガホンを加えます |
audio.mix(input) | 複数のトラックを重ねて 1 つにします |
audio.adjustVolume(input) | レベルの変更、ノーマライズ、フェードを行います |
audio.combine(input) | オーディオのセグメントを順番につなげます |
audio.transcribe(input) | 単語のタイミング付きで、音声をテキストにします |
client.voices:ボイス
voices.list()
ElevenLabs の標準ボイスを一覧表示します(GET /v1/voices)。サーバーに ElevenLabs のキーが設定されていない場合は、代わりに厳選されたセットを返します。
list(): Promise<Voice[]>const voices = await client.voices.list()voices.searchLibrary(params?)
コミュニティのボイスライブラリを検索します(GET /v1/voices/library)。どのパラメーターも任意で、空の値は取り除かれるため、サーバーのデフォルトが適用されます。応答の hasMore で、次のページがあるかどうかがわかります。
searchLibrary(params?: VoiceLibraryParams): Promise<{ voices: Voice[]; hasMore: boolean }>Prop
Type
const { voices, hasMore } = await client.voices.searchLibrary({ search: "deep", language: "en" })
const voice = voices[0]
await client.nodes.run("text-to-speech", {
text: "Hello!",
voice: voice.voice_id,
voiceType: "library",
...(voice.recommendedProvider ? { provider: voice.recommendedProvider } : {}),
})各ボイスには、そのボイスが検証済みの音声モデルについて、2 つのヒントが付くことがあります。
recommendedProviderは、そのボイスに最適なモデルです。モデルピッカーのないアプリは、これをproviderとしてテキストから音声(Text to Speech)に送ってください。そうすると、ボイスがライブラリのプレビューと同じように聞こえます。verifiedProvidersは、そのボイスが検証済みのすべてのモデルを一覧にします。モデルピッカーのあるアプリは、ユーザーの選んだモデルがこの一覧にない場合にだけ、それを置き換えてください。
voices.listClones()
自分のボイスクローンを一覧表示します(GET /v1/voice-clones)。クローン機能が廃止される前に作ったクローンは、ボイスを指定できるところならどこでも、ボイス ID として引き続き使えます。
listClones(): Promise<VoiceClone[]>const clones = await client.voices.listClones()voices.deleteClone(id)
自分のボイスクローンの 1 つを削除します(DELETE /v1/voice-clones/:id)。
deleteClone(id: string): Promise<void>Prop
Type
await client.voices.deleteClone(cloneId)voices.createClone() と createCloneFromFile()
ボイスクローンの作成は、Nodaro ではもう提供されていません。2026 年 9 月に廃止されました。両方のメソッドはクライアントに残っていますが、非推奨として示されます。code が voice_cloning_retired の NodaroError を、ステータス 410 でスローします。新しいカスタムボイスには、代わりに design() を使ってください。
client.voices:ボイスチェンジャー
voices.change(input)
録音や、話している動画全体の声を、別の声に置き換えます(POST /v1/voice-changer)。ボイスチェンジャー(Voice Changer)ノードと同じ処理です。videoUrl を指定すると、サーバーは動画から音声を取り出し、声を変換して、新しい声を元の映像に載せ直します。
change(input: {
voiceId: string
audioUrl?: string
videoUrl?: string
model?: string
stability?: number
similarityBoost?: number
style?: number
useSpeakerBoost?: boolean
seed?: number
removeBackgroundNoise?: boolean
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.change({
videoUrl: "https://example.com/talking.mp4",
voiceId: "Aria",
})
// the finished job's output_data has videoUrl and audioUrlvoices.recast(input)
録音の中で検出された各話者に、それぞれ異なるボイスを割り当てます(POST /v1/voice-changer-pro)。ボイスチェンジャー Pro(Voice Changer Pro)ノードと同じ処理です。Nodaro Cloud で実行され、クレジットがかかり、ジョブとして実行されます。
recast(input: VoiceChangerProInput): Promise<{ jobId: string }>Prop
Type
orderedVoices の各エントリーは、次のいずれかです。
- ボイス ID:
"Rachel"のような標準ボイスの名前か、ElevenLabs のボイス ID です。 null:元の声を維持するスロットです。その話者は自分の声のままですが、それより後の話者は引き続き差し替えられます。差し替える話者にだけ料金がかかるため、維持するスロットは無料です。- オブジェクト:
voiceIdと、その話者の設定です。stability、similarityBoost、styleは 0〜1、useSpeakerBoost、seedは 0〜4,294,967,295 です。volumeModeは"match"(デフォルト、元の話者のレベル)、"normalize"、またはvolumeを 0〜200% で指定する"manual"のいずれかです。engine: "v3"は、録音した音声を変換する代わりに、その話者のセリフを文字起こしから読み上げ直します。[audio tags]にも対応します。
話者 0 には orderedVoices[0] が、話者 1 には orderedVoices[1] が割り当てられ、以降も同様です。最後のエントリーより後の話者は、自分の声のままです。声と音楽は、常に最初に分離されます。preserveBackground が決めるのは、音楽を戻すかどうかだけです。
voiceFx.preset は、リバーブの空間(room、bathroom、car、hall、concert-hall、church、cave、arena、outdoor)か、telephone、megaphone、echo、custom のいずれかです。リバーブのプリセットは、0〜100 の wetDryMix を使います。echo と custom は、20〜2,000 の delayMs と、0〜1 の decay を使います。
// Recast speakers 1 and 3, and keep speaker 2's own voice
const { jobId } = await client.voices.recast({
audioUrl: "https://example.com/panel.mp3",
orderedVoices: ["Rachel", null, "Aria"],
})
// Repeatable voices, a hall reverb, and finer separation
const { jobId: tuned } = await client.voices.recast({
audioUrl: "https://example.com/dialogue.mp3",
orderedVoices: [
{ voiceId: "Rachel", seed: 12345, stability: 0.6 },
{ voiceId: "Aria", seed: 67890, volumeMode: "manual", volume: 120 },
],
voiceFx: { preset: "hall", wetDryMix: 35 },
separationQuality: "best",
})動画モードでは、完了したジョブの output_data に videoUrl と audioUrl が入ります。
voices.analyze(input)
クリップの話者を、差し替えずに検出します(POST /v1/voice-changer-pro/analyze)。声を音楽から 1 回分離し、誰がいつ話しているかを調べます。Nodaro Cloud で実行され、料金は一律で、ジョブとして実行されます。
analyze(input: {
audioUrl?: string
videoUrl?: string
separationQuality?: "fast" | "best"
suggestTitle?: boolean
}): Promise<{ jobId: string }>Prop
Type
完了したジョブの output_data は VcpAnalysis です。分離した vocalsUrl と backgroundUrl、検出された speakers(それぞれに id、時間の segments、firstStartSec、wordCount、テキストの snippet を含む)、languageProbability を伴う languageCode、依頼した場合は suggestedTitle が含まれます。これを、後で呼び出す recast() に analysis として渡すと、分離済みのトラックが再利用され、検出のための料金がもう一度かかることはありません。
voices.exportMix(input)
ミックスしたステムから、最終的な動画をレンダリングします(POST /v1/voice-changer-pro/export)。recast({ output: "stems" }) の後に行う、最後のステップです。Nodaro Cloud で実行され、料金は一律で、ジョブとして実行されます。
exportMix(input: {
videoUrl: string
tracks: Array<{ url: string; gain: number; muted: boolean; kind?: "voice" | "background" }>
voiceFx?: { preset: AudioFxPreset; wetDryMix?: number; delayMs?: number; decay?: number }
}): Promise<{ jobId: string }>Prop
Type
対話的なフローでは、1 回分析し、ステムに差し替え、その後ミックスしてレンダリングします。以下は、簡単なポーリング用のヘルパーを使った例です。
import type { VcpAnalysis } from "@nodaro/sdk"
async function outputOf(jobId: string): Promise<any> {
for (;;) {
const { data } = await client.jobs.getStatus(jobId)
if (data.status === "completed") return data.output_data
if (data.status === "failed" || data.status === "cancelled") throw new Error(data.error_message ?? data.status)
await new Promise((resolve) => setTimeout(resolve, 2_000))
}
}
const { jobId: analyzeJob } = await client.voices.analyze({ videoUrl })
const analysis = (await outputOf(analyzeJob)) as VcpAnalysis
const { jobId: recastJob } = await client.voices.recast({
videoUrl,
orderedVoices: ["Rachel", null, "Aria"],
output: "stems",
analysis,
})
const stems = await outputOf(recastJob)
const { jobId: exportJob } = await client.voices.exportMix({
videoUrl,
tracks: [
{ url: stems.tracks[0].url, gain: 100, muted: false },
{ url: stems.tracks[1].url, gain: 90, muted: false },
{ url: stems.backgroundUrl, gain: 70, muted: false, kind: "background" },
],
voiceFx: { preset: "hall", wetDryMix: 25 },
})
const { videoUrl: finalVideo } = await outputOf(exportJob)ゲイン、ミュート、エフェクトは、動画をレンダリングするときに適用され、映像はそのままコピーされます。そのため、エクスポートの結果はプレビューと一致し、エクスポートするまでは、好きなだけミックスを変更できます。すべてのトラックをミュートしたミックスは、400 で拒否されます。
client.voices:作成と翻訳
voices.design(input)
文章による説明から、新しい合成ボイスを作成します(POST /v1/voice-design)。ボイスデザイン(Voice Design)ノードと同じ処理です。完了したジョブには、オーディオのプレビューと、新しいボイスの ID が含まれ、ボイスを指定できるところならどこでも使えます。
design(input: {
text: string
voiceDescription: string
model?: string
loudness?: number
guidanceScale?: number
seed?: number
quality?: number
shouldEnhance?: boolean
userPrompt?: string
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.design({
text: "Welcome back. Tonight we follow the river north, into the mountains where the story began.",
voiceDescription: "A calm, deep voice of an older male narrator with a slight British accent",
})voices.remix(input)
わかりやすい言葉で説明したボイスでテキストを話します。ボイスを作成することはありません(POST /v1/voice-remix)。ボイスリミックス(Voice Remix)ノードと同じ処理です。
remix(input: { text: string; voiceDescription: string; userPrompt?: string }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.remix({
text: "Your order is on its way.",
voiceDescription: "A cheerful young woman, fast and upbeat",
})voices.dub(input)
オーディオ、または動画全体を、各話者の声を保ったまま別の言語に吹き替えます(POST /v1/dubbing)。吹き替え(Dubbing)ノードと同じ処理です。動画の吹き替えでは、吹き替えたクリップである output_data.videoUrl と、吹き替えたトラックのみの output_data.audioUrl が返ります。
dub(input: DubbingInput): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.dub({
videoUrl: "https://example.com/interview.mp4",
targetLanguage: "es",
numSpeakers: 2,
})料金は、吹き替える区間の分数によって決まり、最低 1 分として計算されます。区間は最長 30 分なので、それより長いソースには startTime と endTime を使ってください。
voices.textToDialogue(input)
複数の話者による脚本を、1 つのオーディオファイルとして音声にします(POST /v1/text-to-dialogue)。テキストから会話(Text to Dialogue)ノードが ElevenLabs Dialogue v3 で行うのと同じ処理です。
textToDialogue(input: {
dialogue: Array<{ text: string; voice: string }>
stability?: 0 | 0.5 | 1
languageCode?: string
seed?: number
applyTextNormalization?: "auto" | "on" | "off"
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.voices.textToDialogue({
dialogue: [
{ text: "Did you hear that?", voice: "Rachel" },
{ text: "[whispers] Stay behind me.", voice: "Callum" },
],
})脚本は最大 5,000 文字まで使え、2,000 文字未満だと最も高品質になります。使えるボイスは最大 10 種類です。ボイスライブラリのボイス、デザインしたボイス、既存のクローンはどれも使えて、自由に組み合わせられます。完了したジョブの output_data.audioUrl が、そのファイルです。
client.audio
ボイスチェンジャー Pro が内部で使っているオーディオの構成要素で、1 つずつ個別に使えます。どのメソッドも jobId を返します。
audio.separate(input)
トラックをステムに分割します(POST /v1/audio-separation)。音源分離(Audio Separation)ノードと同じ処理です。
separate(input: { audioUrl: string; mode?: "vocal_instrumental" | "stems"; quality?: "auto" | "fast" | "best" }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.separate({ audioUrl: songUrl })
// output: vocalUrl and instrumentalUrl, or one URL per stem in stems modeaudio.isolate(input)
主な声を残し、背景ノイズを取り除きます(POST /v1/audio-isolation)。音声抽出(Voice Extractor)ノードと同じ処理です。
isolate(input: { audioUrl: string }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.isolate({ audioUrl: interviewUrl })audio.applyFx(input)
リバーブ、エコー、電話、メガホンのエフェクトを加えます(POST /v1/audio-fx)。オーディオ FX(Audio FX)ノードと同じ処理です。プリセットは、ボイスチェンジャーの voiceFx と同じです。
applyFx(input: {
audioUrl: string
preset?: AudioFxPreset
mix?: number
delayMs?: number
decay?: number
eqLow?: number
eqHigh?: number
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.applyFx({ audioUrl: lineUrl, preset: "telephone" })audio.mix(input)
複数のトラックを重ねて 1 つにします(POST /v1/mix-audio)。オーディオをミックス(Mix Audio)ノードと同じ処理です。
mix(input: { audioUrls: string[]; trackVolumes?: number[] }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.mix({ audioUrls: [voiceUrl, musicUrl], trackVolumes: [100, 35] })audio.adjustVolume(input)
オーディオファイル、または動画の音の音量を変更します(POST /v1/adjust-volume)。音量調整(Adjust Volume)ノードと同じ処理です。
adjustVolume(input: {
audioUrl?: string
videoUrl?: string
volume?: number
normalize?: boolean
fadeIn?: number
fadeOut?: number
}): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.adjustVolume({ audioUrl: musicUrl, volume: 60, fadeOut: 3 })audio.combine(input)
オーディオのセグメントを順番につなげます(POST /v1/combine-audio)。オーディオを結合(Combine Audio)ノードと同じ処理です。
combine(input: { segments: Array<{ url: string; startTime?: number; endTime?: number }> }): Promise<{ jobId: string }>Prop
Type
const { jobId } = await client.audio.combine({
segments: [{ url: introUrl }, { url: episodeUrl, startTime: 4 }, { url: outroUrl }],
})audio.transcribe(input)
オーディオまたは動画ファイルの音声をテキストにします(POST /v1/transcribe)。文字起こし(Transcribe)ノードと同じ処理です。
transcribe(input: {
audioUrl: string
provider?: "elevenlabs-stt" | "incredibly-fast-whisper" | "whisper"
language?: string
diarize?: boolean
tagAudioEvents?: boolean
wordTimestamps?: boolean
}): Promise<{ jobId: string }>Prop
Type
provider | 単語のタイミング | 備考 |
|---|---|---|
elevenlabs-stt | 常に返す | diarize と tagAudioEvents に対応する唯一のエンジンです。 |
incredibly-fast-whisper | wordTimestamps: true のときだけ | このフラグがない場合、ジョブは成功して課金されますが、フレーズ単位のセグメントのみで、words は空のリストになります。 |
whisper | 返さない | フレーズ単位のセグメントのみです。wordTimestamps: true を指定すると、クレジットが使われる前に 400 validation_error で拒否されます。 |
provider を省略すると whisper が使われるため、provider を指定しない wordTimestamps: true も、同じ 400 になります。単語のタイミングが必要な場合は、elevenlabs-stt を指定するか、wordTimestamps: true を付けた incredibly-fast-whisper を指定してください。キネティックスタイルの字幕には、これが必要です。
const { jobId } = await client.audio.transcribe({ audioUrl: talkUrl, provider: "elevenlabs-stt" })完了したジョブの output_data は TranscribeJobOutput です。
| フィールド | 単位 | 内容 |
|---|---|---|
text | 文字起こし全体を、1 つの文字列にしたものです。 | |
language | 検出された、または指定した言語コードです。 | |
words | ミリ秒 | 単語ごとに 1 件で、{ text, startMs, endMs, speaker? } の形です。エンジンに単語のタイミングを求めなかった場合は空です。 |
json | ミリ秒 | 正規化された文字起こしで、{ version, language, words, segments? } の形です。client.edit が受け取る形式です。 |
segments | 秒 | 元のフレーズの範囲で、古いエンジンのみが返します。elevenlabs-stt は返さないので、words を読み取ってください。 |
words は、client.media.addCaptions() が受け取る captions と、まったく同じ形です。そのため、文字起こしを修正して、そのまま字幕として焼き込めます。
よくある質問
関連ページ
メディアとアップロード
編集
音声とメディア
ボイスチェンジャー Pro
文字起こし
最終更新