메인 콘텐츠로 건너뛰기
타입캐스트 API를 위한 공식 Swift 라이브러리입니다. AI 기반 음성을 사용하여 텍스트를 생동감 있는 음성으로 변환하세요. Swift 5.9 이상과 호환되며 모든 Apple 플랫폼을 지원합니다: iOS, macOS, tvOS, watchOS, visionOS.

Swift Package

Typecast Swift SDK

소스 코드

Typecast Swift SDK 소스 코드

요구 사항

플랫폼최소 버전
iOS13.0+
macOS10.15+
tvOS13.0+
watchOS6.0+
visionOS1.0+
Swift5.9+

설치

Package.swift에 다음을 추가하세요:
dependencies: [
    .package(url: "https://github.com/neosapience/typecast-sdk.git", from: "1.0.0")
]
그런 다음 타겟 의존성에 Typecast를 추가하세요:
targets: [
    .target(
        name: "YourTarget",
        dependencies: ["Typecast"]
    )
]
Swift 5.9 이상이 설치되어 있는지 확인하세요. SDK는 이 최소 버전이 필요한 Swift Concurrency(async/await)를 사용합니다.

빠른 시작

import Typecast

let client = TypecastClient(apiKey: "YOUR_API_KEY")

// 편의 메서드로 간단하게 사용
let audio = try await client.speak(
    "안녕하세요! 저는 텍스트 음성 변환 에이전트입니다.",
    voiceId: "tc_672c5f5ce59fac2a48faeaee"
)

// 파일로 저장
let url = URL(fileURLWithPath: "output.\(audio.format.rawValue)")
try audio.audioData.write(to: url)
print("Audio saved! Duration: \(audio.duration)s, Format: \(audio.format.rawValue)")

기능

Typecast Swift SDK는 텍스트 음성 변환을 위한 강력한 기능을 제공합니다:
  • 다중 음성 모델: 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
  • Swift Concurrency: 현대적인 Swift 개발을 위한 완전한 async/await 지원
  • 스레드 안전: 안전한 동시 사용을 위해 모든 타입이 Sendable을 준수
  • 스트리밍: 저지연 재생을 위한 실시간 청크 오디오 전송
  • 크로스 플랫폼: iOS, macOS, tvOS, watchOS, visionOS에서 작동

구성

API 키로 클라이언트를 초기화하세요:
import Typecast

// 직접 초기화
let client = TypecastClient(apiKey: "your-api-key")

// 사용자 정의 base URL과 함께
let client = TypecastClient(
    apiKey: "your-api-key",
    baseURL: "https://api.typecast.ai"
)

// 구성 구조체 사용
let config = TypecastConfiguration(apiKey: "your-api-key")
let client = TypecastClient(configuration: config)

고급 사용법

감정 제어 (ssfm-v30)

ssfm-v30은 두 가지 감정 제어 모드를 제공합니다: 프리셋스마트.
AI가 문맥에서 감정을 추론하도록 합니다:
let request = TTSRequest(
    voiceId: "tc_672c5f5ce59fac2a48faeaee",
    text: "모든 것이 잘 될 거예요.",
    model: .ssfmV30,
    prompt: .smart(SmartPrompt(
        previousText: "방금 최고의 소식을 들었어요!",  // 선택적 문맥
        nextText: "축하할 수 있어서 너무 기다려져요!"     // 선택적 문맥
    ))
)

let response = try await client.textToSpeech(request)

오디오 사용자 정의

라우드니스, 피치, 템포 및 출력 형식을 제어합니다:
let request = TTSRequest(
    voiceId: "tc_672c5f5ce59fac2a48faeaee",
    text: "사용자 정의 오디오 출력!",
    model: .ssfmV30,
    output: OutputSettings(
        targetLufs: -14.0,     // 범위: -70 ~ 0 (LUFS)
        audioPitch: 2,        // 범위: -12 to +12 반음
        audioTempo: 1.2,      // 범위: 0.5x to 2.0x
        audioFormat: .mp3     // 옵션: .wav, .mp3
    ),
    seed: 42  // 부호 없는 정수 시드 (재현 가능한 결과)
)

let response = try await client.textToSpeech(request)

try response.audioData.write(to: URL(fileURLWithPath: "output.\(response.format.rawValue)"))
print("Duration: \(response.duration)s, Format: \(response.format.rawValue)")

음성 탐색 (V2 API)

향상된 메타데이터로 사용 가능한 음성을 나열하고 필터링합니다:
// 모든 음성 가져오기
let voices = try await client.getVoices()

// 기준으로 필터링
let filteredVoices = try await client.getVoices(filter: VoicesV2Filter(
    model: .ssfmV30,
    gender: .female,
    age: .youngAdult
))

// 특정 음성 가져오기
let voice = try await client.getVoice(voiceId: "tc_672c5f5ce59fac2a48faeaee")

// 음성 정보 표시
print("ID: \(voice.voiceId), Name: \(voice.voiceName)")
print("Gender: \(voice.gender?.rawValue ?? "N/A"), Age: \(voice.age?.rawValue ?? "N/A")")

for model in voice.models {
    print("Model: \(model.version.rawValue), Emotions: \(model.emotions.joined(separator: ", "))")
}

if let useCases = voice.useCases {
    print("Use cases: \(useCases.joined(separator: ", "))")
}

다국어 콘텐츠

SDK는 자동 언어 감지와 함께 37개 언어를 지원합니다:
// 자동 언어 감지 (권장)
let request = TTSRequest(
    voiceId: "tc_672c5f5ce59fac2a48faeaee",
    text: "こんにちは。お元気ですか。",
    model: .ssfmV30
)

let response = try await client.textToSpeech(request)

// 또는 언어를 명시적으로 지정
let koreanRequest = TTSRequest(
    voiceId: "tc_672c5f5ce59fac2a48faeaee",
    text: "안녕하세요. 반갑습니다.",
    model: .ssfmV30,
    language: .korean  // 명시적 언어 코드
)

let koreanResponse = try await client.textToSpeech(koreanRequest)

try koreanResponse.audioData.write(to: URL(fileURLWithPath: "output.wav"))

스트리밍

저지연 재생을 위한 실시간 오디오 청크 스트리밍:
import AVFoundation
import Typecast

let engine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 32000, channels: 1, interleaved: true)!

engine.attach(playerNode)
engine.connect(playerNode, to: engine.mainMixerNode, format: format)
try engine.start()
playerNode.play()

let stream = try await client.textToSpeechStream(request)
var first = true

for try await chunk in stream {
    var pcmData = chunk
    if first {
        pcmData = chunk.dropFirst(44)  // 44바이트 WAV 헤더 건너뛰기
        first = false
    }
    let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(pcmData.count / 2))!
    buffer.frameLength = buffer.frameCapacity
    pcmData.withUnsafeBytes { ptr in
        buffer.int16ChannelData!.pointee.update(from: ptr.bindMemory(to: Int16.self).baseAddress!, count: Int(buffer.frameLength))
    }
    playerNode.scheduleBuffer(buffer)
}
WAV 스트리밍 형식: 32000 Hz, 16비트, 모노 PCM. 첫 번째 청크에 44바이트 WAV 헤더(size = 0xFFFFFFFF)가 포함되며, 이후 청크는 원시 PCM 데이터만 포함합니다. MP3 형식: 320 kbps, 44100 Hz, 각 청크는 독립적으로 디코딩 가능합니다. Foundation.OutputStream과의 이름 충돌을 피하려면 Typecast.OutputStream을 사용하세요. 스트리밍 엔드포인트는 volumetargetLufs를 지원하지 않습니다.

지원 언어

SDK는 자동 언어 감지와 함께 37개 언어를 지원합니다:
코드언어코드언어코드언어
.english영어.japanese일본어.ukrainian우크라이나어
.korean한국어.greek그리스어.indonesian인도네시아어
.spanish스페인어.tamil타밀어.danish덴마크어
.german독일어.tagalog타갈로그어.swedish스웨덴어
.french프랑스어.finnish핀란드어.malay말레이어
.italian이탈리아어.chinese중국어.czech체코어
.polish폴란드어.slovak슬로바키아어.portuguese포르투갈어
.dutch네덜란드어.arabic아랍어.bulgarian불가리아어
.russian러시아어.croatian크로아티아어.romanian루마니아어
.bengali벵골어.hindi힌디어.hungarian헝가리어
.minNan민난어.norwegian노르웨이어.punjabi펀자브어
.thai태국어.turkish터키어.vietnamese베트남어
.cantonese광둥어
지정하지 않으면 입력 텍스트에서 언어가 자동으로 감지됩니다.

오류 처리

SDK는 API 오류 처리를 위한 포괄적인 TypecastError 열거형을 제공합니다:
import Typecast

do {
    let response = try await client.textToSpeech(request)
} catch let error as TypecastError {
    switch error {
    case .unauthorized(let message):
        // 401: 잘못된 API 키
        print("Invalid API key: \(message)")
    case .paymentRequired(let message):
        // 402: 크레딧 부족
        print("Insufficient credits: \(message)")
    case .notFound(let message):
        // 404: 리소스를 찾을 수 없음
        print("Voice not found: \(message)")
    case .validationError(let message):
        // 422: 유효성 검사 오류
        print("Validation error: \(message)")
    case .rateLimitExceeded(let message):
        // 429: 요청 한도 초과
        print("Rate limit exceeded: \(message)")
    case .serverError(let message):
        // 500: 서버 오류
        print("Server error: \(message)")
    case .networkError(let underlyingError):
        // 네트워크 연결 문제
        print("Network error: \(underlyingError.localizedDescription)")
    case .invalidResponse(let message):
        // 서버의 잘못된 응답
        print("Invalid response: \(message)")
    default:
        print("Error: \(error.localizedDescription)")
    }
    
    // 사용 가능한 경우 상태 코드에 액세스
    if let statusCode = error.statusCode {
        print("HTTP status: \(statusCode)")
    }
}

오류 타입

오류상태 코드설명
.badRequest400잘못된 요청 매개변수
.unauthorized401잘못되거나 누락된 API 키
.paymentRequired402크레딧 부족
.notFound404리소스를 찾을 수 없음
.validationError422유효성 검사 오류
.rateLimitExceeded429요청 한도 초과
.serverError500서버 오류
.networkError-네트워크 연결 문제
.invalidResponse-서버의 잘못된 응답

플랫폼별 사용법

iOS

import Typecast
import AVFoundation

class TTSManager {
    private let client = TypecastClient(apiKey: "YOUR_API_KEY")
    private var audioPlayer: AVAudioPlayer?
    
    func speak(_ text: String) async throws {
        let audio = try await client.speak(text, voiceId: "tc_672c5f5ce59fac2a48faeaee")
        
        // 데이터에서 직접 오디오 재생
        audioPlayer = try AVAudioPlayer(data: audio.audioData)
        audioPlayer?.play()
    }
}

macOS

import Typecast
import AppKit
import AVFoundation

class MacTTSManager {
    private let client = TypecastClient(apiKey: "YOUR_API_KEY")
    private var audioPlayer: AVAudioPlayer?
    
    func speak(_ text: String) async throws {
        let audio = try await client.speak(text, voiceId: "tc_672c5f5ce59fac2a48faeaee")
        
        audioPlayer = try AVAudioPlayer(data: audio.audioData)
        audioPlayer?.play()
    }
    
    func saveWithPanel(_ text: String) async throws {
        let audio = try await client.speak(text, voiceId: "tc_672c5f5ce59fac2a48faeaee")
        
        let savePanel = NSSavePanel()
        savePanel.allowedContentTypes = [.audio]
        savePanel.nameFieldStringValue = "speech.\(audio.format.rawValue)"
        
        if savePanel.runModal() == .OK, let url = savePanel.url {
            try audio.audioData.write(to: url)
        }
    }
}

watchOS

import Typecast
import WatchKit

class WatchTTSManager {
    private let client = TypecastClient(apiKey: "YOUR_API_KEY")
    
    func speak(_ text: String) async throws {
        let audio = try await client.speak(text, voiceId: "tc_672c5f5ce59fac2a48faeaee")
        
        // 임시 파일에 저장하고 재생
        let tempURL = FileManager.default.temporaryDirectory
            .appendingPathComponent("speech.\(audio.format.rawValue)")
        try audio.audioData.write(to: tempURL)
        
        // watchOS용 WKAudioFilePlayer 사용
        let asset = WKAudioFileAsset(url: tempURL)
        let playerItem = WKAudioFilePlayerItem(asset: asset)
        let player = WKAudioFilePlayer(playerItem: playerItem)
        player.play()
    }
}

API 레퍼런스

TypecastClient 메서드

메서드설명
textToSpeech(_:)텍스트를 음성 오디오로 변환
speak(_:voiceId:model:)최소 매개변수로 간단한 TTS
speak(_:voiceId:model:emotion:intensity:)감정 프리셋으로 TTS
getVoices(filter:)선택적 필터로 사용 가능한 음성 가져오기
getVoice(voiceId:)ID로 특정 음성 가져오기

TTSRequest 필드

필드타입필수설명
voiceIdString음성 ID (형식: tc_*)
textString합성할 텍스트 (최대 2000자)
modelTTSModelTTS 모델 (.ssfmV21 또는 .ssfmV30)
languageLanguageCode언어 코드 (생략 시 자동 감지)
promptTTSPrompt감정 설정 (.basic, .preset, 또는 .smart)
outputOutputSettings오디오 출력 설정
seedUInt32재현성을 위한 부호 없는 정수 시드 (≥ 0)

TTSResponse 필드

필드타입설명
audioDataData생성된 오디오 데이터
durationTimeInterval오디오 길이 (초)
formatAudioFormat오디오 형식 (.wav 또는 .mp3)