广告位招商中 欢迎洽谈

如何集成 Uberduck API 程序化生成 AI 说唱与歌唱人声

365Finds Editorial
已收录 11,430 篇 Wiki 文章

让你的 AI 用上 365 Wiki

复制这段快捷提示词,粘贴到你正在使用的 AI 对话中,然后继续提问。AI 会搜索 365 Wiki,帮你查资料、比较方案并给出建议。

下载完整 Skill

偶尔使用,快捷提示词就够了。经常使用,安装 365Wiki Skill:无需每次复制,还能更完整地研究问题、比较选择并规划下一步。没有常用工具?Gemini、Microsoft Copilot 等网页版 AI 也能使用。

365Wiki Skill

在开发交互式音乐应用、游戏 NPC 实时演唱或虚拟主播(VTuber)音频生成系统时,许多工程师和创意技术人员常受限于网页端的手动操作界面:基于浏览器的生成模式无法嵌入自动化流水线,也无法承受高并发与自动化批处理。Uberduck 提供了官方 REST API,使开发者能够直接在代码中程序化合成具有节奏感和旋律感的声音资产。

要在后端成功集成 Uberduck API 来生成唱歌与说唱人声,主要涵盖三个关键架构层:HTTP Basic 鉴权、选择适配的合成模式(基于节奏对齐的 /tts/freestyle 端点、参数化音高时间轴 /speak 或声音转换 /tts/convert),以及基于 /speak-status 的高并发异步任务轮询机制。


1. 鉴权机制与请求架构

Uberduck 官方 REST API 采用标准的 HTTP Basic Authentication 协议。开发者需要将控制台获取的 API Key(作为用户名)与 API Secret(作为密码)合并并进行 Base64 编码,放入 HTTP 请求头中。

鉴权请求头构建

  1. 在 Uberduck 账号设置中生成 API Key 与 API Secret。
  2. 构造 HTTP Authorization 请求头:
    Authorization: Basic base64(API_KEY:API_SECRET)
    
  3. API 基础端点地址为 https://api.uberduck.ai。
import base64
import os

API_KEY = os.getenv("UBERDUCK_API_KEY", "your_api_key")
API_SECRET = os.getenv("UBERDUCK_API_SECRET", "your_api_secret")

def get_auth_headers():
    token = base64.b64encode(f"{API_KEY}:{API_SECRET}".encode("utf-8")).decode("utf-8")
    return {
        "Authorization": f"Basic {token}",
        "Content-Type": "application/json"
    }

2. 三种核心人声合成模式对比

针对说唱歌词与旋律歌唱的不同场景,Uberduck 提供了三种实现路径:

合成模式核心端点关键参数适用场景
文本到说唱(Freestyle)POST /tts/freestylelyrics, bpm, backing_track, voice 或 voicemodel_uuid生成具有节拍卡点的说唱音频;互动式即兴饶舌;动态定制歌词管线
参数化音高与时长合成POST /speakspeech, voicemodel_uuid, pitch, duration, pace依照 MIDI 或旋律简谱精确驱动音高曲线与音素长度的乐曲合成
声音转换(Voice-to-Voice)POST /tts/convertvoicemodel_uuid, input(音频 URL), pitch_shift富有自然颤音与滑音的旋律歌唱;以导唱音频或合成器音轨为基准转换音色

3. 构建端到端程序化说唱合成管线

/tts/freestyle 是专门为说唱设计的端点,其底层模型能根据节拍速度(BPM)和伴奏音轨结构自动吸附押韵节拍。

步骤 1:查询官方伴奏库

如果希望人声与官方伴奏精准匹配,可先获取预置伴奏列表:

import requests

def list_backing_tracks():
    url = "https://api.uberduck.ai/reference-audio/backing-tracks?detailed=true"
    response = requests.get(url, headers=get_auth_headers())
    response.raise_for_status()
    return response.json()  # 返回包含伴奏 UUID、BPM 与风格元数据的列表

步骤 2:(可选)自动生成押韵歌词

若应用包含“根据主题生成即兴说唱”的逻辑,可通过 /tts/lyrics 调用歌词生成接口(或自建大模型生成二维字符串数组格式):

def generate_lyrics(subject, lines=4):
    url = "https://api.uberduck.ai/tts/lyrics"
    payload = {
        "subject": subject,
        "lines": lines
    }
    response = requests.post(url, json=payload, headers=get_auth_headers())
    response.raise_for_status()
    return response.json()  # 返回结构化歌词行

步骤 3:发起 Freestyle 异步生成请求

将结构化歌词矩阵(以二维数组划分段落与单句)、目标 BPM、伴奏 UUID 以及声音模型参数提交给 API:

def generate_rap_vocal(lyrics_matrix, bpm=90, backing_track_uuid=None, voice="zwf"):
    url = "https://api.uberduck.ai/tts/freestyle"
    payload = {
        "lyrics": lyrics_matrix,  # 例如:[["代码在终端翻滚节拍永不停歇", "函数调用人声在音轨穿梭"]]
        "bpm": bpm,
        "voice": voice,
        "format": "json"
    }
    if backing_track_uuid:
        payload["backing_track"] = backing_track_uuid

    response = requests.post(url, json=payload, headers=get_auth_headers())
    response.raise_for_status()
    data = response.json()
    return data["uuid"]  # 返回异步任务 UUID

4. 配置音高时间轴与旋律歌唱人声

与注重节奏卡点的说唱不同,旋律性歌唱对连续音高和音素持续时长有极高要求。Uberduck 提供了两种实现思路:

方案 A:通过 /speak 控制音高曲线与音素长度

在支持细粒度控制的声音模型中(可通过 GET /voices/{voicemodel_uuid}/detail 检查响应中的 controls: true),/speak 允许传入 pitch(音高数组)和 duration(时长数组):

def generate_singing_notes(speech_text, voicemodel_uuid, pitch_curve, duration_curve):
    """
    pitch_curve: 对应每个音素的目标基频或半音值的数值数组
    duration_curve: 对应每个音素持续时间的数值数组
    """
    url = "https://api.uberduck.ai/speak"
    payload = {
        "speech": speech_text,
        "voicemodel_uuid": voicemodel_uuid,
        "pitch": pitch_curve,
        "duration": duration_curve,
        "pace": 1.0
    }
    response = requests.post(url, json=payload, headers=get_auth_headers())
    response.raise_for_status()
    return response.json()["uuid"]

方案 B:利用声音转换(V2V)生成工业级自然歌声

直接计算音素级别的音高和时长曲线难度较高,且容易产生机械感。工业级音乐产品中更通用的做法是采用 Voice-to-Voice(声音转换): 先用轻量级 MIDI 歌唱合成器(如纯净导唱音)或真人录制一条基础导唱,然后通过 POST /tts/convert 接口替换为人气音色,并通过 pitch_shift 进行半音移调:

def convert_guide_vocal_to_singer(guide_audio_url, target_voice_uuid, semitone_shift=0):
    url = "https://api.uberduck.ai/tts/convert"
    payload = {
        "input": guide_audio_url,
        "voicemodel_uuid": target_voice_uuid,
        "pitch_shift": semitone_shift
    }
    response = requests.post(url, json=payload, headers=get_auth_headers())
    response.raise_for_status()
    return response.json()["uuid"]

5. 异步生命周期与高并发轮询机制

音频神经网络推理消耗大量算力,无法在单一 HTTP 短连接内即时返回。每次提交任务后,API 会返回一个异步任务 ID(uuid)。后台需要建立具备超时与指数退避机制的轮询器:

import time

def poll_render_completion(job_uuid, max_attempts=30, delay_seconds=2):
    status_url = f"https://api.uberduck.ai/speak-status?uuid={job_uuid}"
    headers = get_auth_headers()
    
    for attempt in range(max_attempts):
        response = requests.get(status_url, headers=headers)
        response.raise_for_status()
        data = response.json()
        
        # 异常失败检测
        if data.get("failed_at"):
            raise RuntimeError(f"音频合成任务失败:{data}")
            
        # 成功完成检测
        if data.get("finished_at"):
            audio_url = data.get("path")
            return audio_url  # 渲染完毕的 CDN 存储地址
            
        time.sleep(delay_seconds)
        
    raise TimeoutError("合成任务超时未完成。")

6. 端到端可执行脚本示例

以下是一份完整的端到端 Python 脚本,涵盖了请求鉴权、任务提交、状态轮询与音频落盘全流程:

import requests
import base64
import time
import os

UBERDUCK_API_KEY = os.getenv("UBERDUCK_API_KEY")
UBERDUCK_API_SECRET = os.getenv("UBERDUCK_API_SECRET")

HEADERS = {
    "Authorization": f"Basic {base64.b64encode(f'{UBERDUCK_API_KEY}:{UBERDUCK_API_SECRET}'.encode()).decode()}",
    "Content-Type": "application/json"
}

def create_rap_track(lyrics, bpm=95, voice="zwf", output_file="vocal_output.wav"):
    # 1. 提交说唱生成任务
    print("正在提交人声合成请求...")
    freestyle_url = "https://api.uberduck.ai/tts/freestyle"
    payload = {
        "lyrics": lyrics,
        "bpm": bpm,
        "voice": voice,
        "format": "json"
    }
    
    resp = requests.post(freestyle_url, json=payload, headers=HEADERS)
    resp.raise_for_status()
    task_id = resp.json()["uuid"]
    print(f"任务已创建,UUID: {task_id}")
    
    # 2. 轮询任务状态
    status_url = f"https://api.uberduck.ai/speak-status?uuid={task_id}"
    audio_url = None
    for _ in range(40):
        time.sleep(2)
        status_resp = requests.get(status_url, headers=HEADERS)
        status_resp.raise_for_status()
        status_data = status_resp.json()
        
        if status_data.get("failed_at"):
            raise RuntimeError("服务端处理任务失败。")
        if status_data.get("finished_at"):
            audio_url = status_data.get("path")
            print(f"音频生成完成,下载地址: {audio_url}")
            break
            
    if not audio_url:
        raise TimeoutError("渲染耗时超过 80 秒,已中止。")
        
    # 3. 下载并持久化音频
    audio_data = requests.get(audio_url).content
    with open(output_file, "wb") as f:
        f.write(audio_data)
    print(f"音频已保存至: {output_file}")
    return output_file

if __name__ == "__main__":
    bars = [
        ["启动生成管线代码注入旋律节奏", "全自动化处理告别人工剪辑操作"],
        ["节拍咬字分毫不差端点持续响应", "Uberduck API 驱动音乐应用全新进化"]
    ]
    create_rap_track(lyrics=bars, bpm=95)

7. 生产环境工程建议与权衡

在将 Uberduck API 部署至商业化生产环境时,应注意以下工程细节:

参考资料