Swift中实现按钮点击同时触发JokesAPI文本获取与Google Text-To-Speech语音合成的技术问询
解决方案:实现按钮点击时获取笑话并转换为语音
首先得指出你现有ChatBotAPI里的几个关键问题:Google Text-to-Speech的API端点不正确,而且请求方式应该是POST(需要提交文本、语音配置等参数),不是你当前使用的GET请求。咱们一步步修正并实现完整功能:
步骤1:修复Google TTS API的调用逻辑
替换原有的ChatBotAPI实现,改成符合Google TTS API要求的POST请求,同时处理音频数据的解码与播放:
import Foundation import AVFoundation class ChatBotAPI { private let API_KEY = "你的Google API密钥" // 替换成你实际的API密钥 private let audioSession = AVAudioSession.sharedInstance() // 将文本转换为语音并播放 func convertTextToSpeech(text: String, completion: @escaping (Bool) -> Void) { // 构造Google TTS要求的请求体 let requestBody: [String: Any] = [ "input": ["text": text], "voice": [ "languageCode": "en-US", "name": "en-US-Standard-C" // 可根据需求更换语音模型 ], "audioConfig": [ "audioEncoding": "MP3" // 指定音频编码格式 ] ] guard let url = URL(string: "https://texttospeech.googleapis.com/v1/text:synthesize?key=\(API_KEY)") else { completion(false) return } var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 序列化请求体 do { request.httpBody = try JSONSerialization.data(withJSONObject: requestBody) } catch { print("请求体序列化失败:\(error)") completion(false) return } let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in guard let self = self else { return } if let error = error { print("API请求错误:\(error.localizedDescription)") completion(false) return } guard let data = data else { print("无返回数据") completion(false) return } // 解析Google TTS的响应(返回base64编码的音频内容) do { let ttsResponse = try JSONDecoder().decode(TTSResponse.self, from: data) guard let audioData = Data(base64Encoded: ttsResponse.audioContent) else { print("音频数据解码失败") completion(false) return } // 播放解码后的音频 self.playAudio(from: audioData) completion(true) } catch { print("响应解析失败:\(error)") completion(false) } } task.resume() } // 播放音频数据 private func playAudio(from data: Data) { do { // 配置音频会话 try audioSession.setCategory(.playback, mode: .default) try audioSession.activate() let audioPlayer = try AVAudioPlayer(data: data) audioPlayer.play() } catch { print("音频播放失败:\(error)") } } } // 对应Google TTS的响应模型 struct TTSResponse: Decodable { let audioContent: String }
步骤2:修改按钮点击事件,串联两个操作
在你的ViewController里,先调用fetchJokes获取笑话文本,拿到有效文本后再触发语音合成:
// 假设你的fetchJokes方法已实现,这里补充带completion的版本(用于异步返回笑话文本) func fetchJokes(completion: @escaping (String?, Error?) -> Void) { // 替换为你实际的JokesAPI端点 guard let url = URL(string: "https://api.your-jokes-source.com/random-joke") else { completion(nil, NSError(domain: "InvalidURL", code: 0, userInfo: [NSLocalizedDescriptionKey: "无效的笑话API地址"])) return } URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { completion(nil, error) return } guard let data = data else { completion(nil, NSError(domain: "NoData", code: 0, userInfo: [NSLocalizedDescriptionKey: "未获取到笑话数据"])) return } // 解析JokesAPI的响应(替换为你实际的数据模型) do { let jokeResponse = try JSONDecoder().decode(Joke.self, from: data) completion(jokeResponse.content, nil) } catch { completion(nil, error) } }.resume() } // 按钮点击事件 @IBAction func didPressBtn() { // 1. 先异步获取笑话文本 fetchJokes { [weak self] jokeText, error in guard let self = self else { return } if let error = error { print("获取笑话失败:\(error.localizedDescription)") // 这里可以添加UI提示,比如弹出alert告诉用户失败原因 return } guard let jokeText = jokeText, !jokeText.isEmpty else { print("未获取到有效笑话内容") return } // 2. 拿到笑话后,调用Google TTS转语音 let ttsAPI = ChatBotAPI() ttsAPI.convertTextToSpeech(text: jokeText) { success in DispatchQueue.main.async { // 可以在这里添加UI反馈,比如按钮状态变化、提示文本 if success { print("语音合成并播放成功") } else { print("语音合成失败") } } } } } // 假设你的JokesAPI数据模型 struct Joke: Decodable { let content: String // 替换为你API返回的笑话字段名 }
关键说明
- API端点修正:Google TTS的正确合成端点是
https://texttospeech.googleapis.com/v1/text:synthesize,必须携带你的API密钥作为URL参数 - 请求方式:必须使用POST请求,提交包含
input(文本内容)、voice(语音配置)、audioConfig(音频格式)的JSON请求体 - 音频处理:Google TTS返回的是base64编码的音频字符串,需要解码成
Data后用AVAudioPlayer播放,同时要配置好音频会话确保播放正常 - 异步串联:按钮点击时先异步获取笑话,拿到结果后再触发语音合成,保证两个操作按顺序执行(先有文本,再转语音)
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

