         AF.request(request)
             .cURLDescription(calling: { log.debug($0) })
             .validate()
-            .responseData {
-                switch $0.result {
-                case .success(let data):
-                    guard let decoded = try? JSONDecoder().decode([VoicevoxSpeakerResponse].self, from: data) else {
-                        completion(Result.failure(.internal))
-                        return
-                    }
-                    completion(Result.success(decoded.toVoicevoxSpeakers()))
-                case .failure(let error):
-                    log.error(error)
-                    completion(Result.failure(.internal))
-                }
+            .responseData { [weak self] in
+                self?.handleSpeakersResponse($0, completion: completion)
             }
     }
 

                completion(Result.failure(.internal))
                return
            }
            if let string = String(bytes: _data, encoding: .utf8) {
                // log.debug(string)
            }
            requestSynthesis(data: _data, config: config, completion: completion)
        case .failure(let error):
            log.error("[\(config.text)] \(error)")

import Foundation
import Alamofire

// XXX: Make the following functions static.
protocol VoicevoxWrapperType {
    func requestSpeakers(completion: @escaping SpeakersRequestCompletion)
    func requestAudio(text: String, speedScale: Float, volumeScale: Float, speaker: Int, completion: @escaping AudioRequestCompletion)
