메인 콘텐츠로 건너뛰기
타입캐스트 API를 위한 공식 Zig 라이브러리입니다. AI 음성을 사용하여 텍스트를 자연스러운 음성으로 변환합니다. 순수 Zig 구현 — C 의존성 없음. Zig 표준 라이브러리의 std.http.Clientstd.json만 사용합니다.

소스 코드

타입캐스트 Zig SDK 소스 코드

패키지

Zig 패키지 (zig fetch)

설치

zig fetch로 의존성을 추가합니다:
zig fetch --save "https://github.com/neosapience/typecast-sdk/archive/refs/tags/typecast-zig/v0.1.0.tar.gz"
그런 다음 build.zig에 import를 추가합니다:
const typecast_dep = b.dependency("typecast_zig", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("typecast", typecast_dep.module("typecast"));

빠른 시작

const std = @import("std");
const typecast = @import("typecast");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // 클라이언트 초기화 (환경변수에서 TYPECAST_API_KEY 읽기)
    var client = typecast.Client.init(allocator, .{
        .api_key = std.posix.getenv("TYPECAST_API_KEY") orelse return error.MissingApiKey,
    });
    defer client.deinit();

    // 텍스트를 음성으로 변환
    const response = try client.textToSpeech(.{
        .voice_id = "tc_672c5f5ce59fac2a48faeaee",
        .text = "안녕하세요! 타입캐스트 Zig SDK입니다.",
        .model = .ssfm_v30,
    });
    defer allocator.free(response.audio_data);

    // 오디오 파일 저장
    const file = try std.fs.cwd().createFile("output.wav", .{});
    defer file.close();
    try file.writeAll(response.audio_data);

    std.debug.print("{d} 바이트 저장, 재생 시간: {d:.1}초\n", .{
        response.audio_data.len, response.duration,
    });
}

기능

  • 다중 음성 모델: ssfm-v30 (최신) 및 ssfm-v21 AI 음성 모델 지원
  • 다국어 지원: 영어, 한국어, 스페인어, 일본어, 중국어 등 37개 언어
  • 감정 제어: 프리셋 감정 (normal, happy, sad, angry, whisper, toneup, tonedown) 또는 스마트 문맥 인식 추론
  • 오디오 커스터마이징: 음량 (LUFS -70 to 0), 피치 (-12 to +12 세미톤), 템포 (0.5x to 2.0x), 포맷 (WAV/MP3) 제어
  • 보이스 탐색: V2 Voices API로 모델, 성별, 나이, 용도별 필터링
  • 순수 Zig: 외부 의존성 없이 표준 라이브러리만 사용
  • 스트리밍: 저지연 재생을 위한 실시간 청크 오디오 전송 (콜백 기반)
  • 명시적 메모리 관리: 호출자 제공 allocator로 명확한 소유권 관리

설정

환경변수 또는 직접 API 키를 전달할 수 있습니다:
const typecast = @import("typecast");

// 환경변수 사용 (권장)
// export TYPECAST_API_KEY="your-api-key-here"
var client = typecast.Client.init(allocator, .{
    .api_key = std.posix.getenv("TYPECAST_API_KEY") orelse return error.MissingApiKey,
});
defer client.deinit();
// 직접 전달
var client = typecast.Client.init(allocator, .{
    .api_key = "your-api-key-here",
});
defer client.deinit();

고급 사용법

감정 제어 (ssfm-v30)

ssfm-v30은 두 가지 감정 제어 모드를 제공합니다: 프리셋스마트.
AI가 문맥에서 감정을 추론합니다:
const response = try client.textToSpeech(.{
    .voice_id = "tc_672c5f5ce59fac2a48faeaee",
    .text = "모든 것이 잘 될 거예요.",
    .model = .ssfm_v30,
    .prompt = .{ .smart = .{
        .previous_text = "방금 최고의 소식을 들었어요!",
        .next_text = "축하하고 싶어요!",
    } },
});
defer allocator.free(response.audio_data);

오디오 커스터마이징

음량, 피치, 템포, 출력 포맷을 제어합니다:
const response = try client.textToSpeech(.{
    .voice_id = "tc_672c5f5ce59fac2a48faeaee",
    .text = "커스터마이징된 오디오 출력!",
    .model = .ssfm_v30,
    .output = .{
        .target_lufs = -14.0,
        .audio_pitch = 2,
        .audio_tempo = 1.2,
        .audio_format = .mp3,
    },
    .seed = 42,
});
defer allocator.free(response.audio_data);

보이스 탐색 (V2 API)

향상된 메타데이터와 함께 사용 가능한 보이스를 조회합니다:
// 모든 보이스 조회
const voices = try client.getVoicesV2(null);
defer allocator.free(voices);

// 모델별 필터링
const filtered = try client.getVoicesV2(.{ .model = .ssfm_v30 });
defer allocator.free(filtered);

for (voices) |voice| {
    std.debug.print("ID: {s}, 이름: {s}\n", .{ voice.voice_id, voice.voice_name });
}

스트리밍

콜백을 통해 실시간으로 오디오 청크를 스트리밍합니다:
try client.textToSpeechStream(.{
    .voice_id = "tc_672c5f5ce59fac2a48faeaee",
    .text = "이 텍스트를 실시간으로 오디오로 스트리밍합니다.",
    .model = .ssfm_v30,
}, struct {
    var first = true;
    fn onChunk(chunk: []const u8) anyerror!void {
        var data = chunk;
        if (first) {
            data = chunk[44..]; // 44바이트 WAV 헤더 건너뛰기
            first = false;
        }
        // data는 32000 Hz 16비트 모노 원시 PCM
        // 오디오 출력으로 전달
    }
}.onChunk);
WAV 스트리밍 형식: 32000 Hz, 16비트, 모노 PCM. 첫 번째 청크에 44바이트 WAV 헤더(size = 0xFFFFFFFF)가 포함되며, 이후 청크는 원시 PCM 데이터만 포함합니다. MP3 형식: 320 kbps, 44100 Hz, 각 청크는 독립적으로 디코딩 가능합니다. 스트리밍 엔드포인트는 volumetarget_lufs를 지원하지 않습니다.

지원 언어

37개 언어를 지원하며 자동 언어 감지 기능을 제공합니다:
코드언어코드언어코드언어
eng영어jpn일본어ukr우크라이나어
kor한국어ell그리스어ind인도네시아어
spa스페인어tam타밀어dan덴마크어
deu독일어tgl타갈로그어swe스웨덴어
fra프랑스어fin핀란드어msa말레이어
ita이탈리아어zho중국어ces체코어
pol폴란드어slk슬로바키아어por포르투갈어
nld네덜란드어ara아랍어bul불가리아어
rus러시아어hrv크로아티아어ron루마니아어
ben벵골어hin힌디어hun헝가리어
nan민난어nor노르웨이어pan펀자브어
tha태국어tur터키어vie베트남어
yue광둥어
언어를 지정하지 않으면 입력 텍스트에서 자동으로 감지됩니다.

에러 처리

SDK는 API 에러 처리를 위해 Zig의 error union을 사용합니다:
const response = client.textToSpeech(.{
    .voice_id = "tc_672c5f5ce59fac2a48faeaee",
    .text = "안녕하세요",
    .model = .ssfm_v30,
}) catch |err| switch (err) {
    error.Unauthorized => {
        std.debug.print("유효하지 않은 API 키\n", .{});
        return err;
    },
    error.PaymentRequired => {
        std.debug.print("크레딧 부족\n", .{});
        return err;
    },
    error.RateLimited => {
        std.debug.print("요청 한도 초과 - 잠시 후 재시도\n", .{});
        return err;
    },
    else => return err,
};
defer allocator.free(response.audio_data);

에러 유형

에러상태 코드설명
error.BadRequest400잘못된 요청 파라미터
error.Unauthorized401유효하지 않거나 누락된 API 키
error.PaymentRequired402크레딧 부족
error.NotFound404리소스를 찾을 수 없음
error.UnprocessableEntity422유효성 검사 오류
error.RateLimited429요청 한도 초과
error.InternalServerError500서버 오류
error.JsonParseError-JSON 파싱 오류

API 레퍼런스

클라이언트 메서드

메서드설명
init(allocator, config)설정으로 클라이언트 생성
deinit()클라이언트 리소스 정리
textToSpeech(request)텍스트를 음성 오디오로 변환
textToSpeechStream(request, callback)콜백을 통한 오디오 청크 스트리밍
getMySubscription()구독 정보 조회
getVoices(model)사용 가능한 보이스 조회 (V1)
getVoicesV2(filter)메타데이터와 함께 보이스 조회 (V2)
getVoiceV2(voice_id, model)특정 보이스 조회