SwiftWhisper

在 Swift 中使用 Whisper 最简单的方式

轻松地将转录功能添加到你的应用程序或软件包中。由 whisper.cpp 驱动。

安装

Swift Package Manager

在你的 Package.swift 文件中将 SwiftWhisper 添加为依赖项

let package = Package(
  ...
  dependencies: [
    // Add the package to your dependencies
    .package(url: "https://github.com/exPHAT/SwiftWhisper.git", branch: "master"),
  ],
  ...
  targets: [
    // Add SwiftWhisper as a dependency on any target you want to use it in
    .target(name: "MyTarget",
            dependencies: [.byName(name: "SwiftWhisper")])
  ]
  ...
)

Xcode

"Swift Package Manager" 标签页中添加 https://github.com/exPHAT/SwiftWhisper.git

用法

API 文档。

import SwiftWhisper

let whisper = Whisper(fromFileURL: /* Model file URL */)
let segments = try await whisper.transcribe(audioFrames: /* 16kHz PCM audio frames */)

print("Transcribed audio:", segments.map(\.text).joined())

代理方法

你可以通过实现 WhisperDelegate 并设置 whisper.delegate = ... 来订阅分段、转录进度和错误。

protocol WhisperDelegate {
  // Progress updates as a percentage from 0-1
  func whisper(_ aWhisper: Whisper, didUpdateProgress progress: Double)

  // Any time a new segments of text have been transcribed
  func whisper(_ aWhisper: Whisper, didProcessNewSegments segments: [Segment], atIndex index: Int)
  
  // Finished transcribing, includes all transcribed segments of text
  func whisper(_ aWhisper: Whisper, didCompleteWithSegments segments: [Segment])

  // Error with transcription
  func whisper(_ aWhisper: Whisper, didErrorWith error: Error)
}

其他

下载模型 📥

你可以在这里找到预训练模型以供下载。

CoreML 支持 🧠

要使用 CoreML,你需要包含一个带有后缀 -encoder.mlmodelc 的 CoreML 模型文件,其名称与 Whisper 模型相同(例如:tiny.bin 旁边也会有一个 tiny-encoder.mlmodelc 文件)。除了额外的模型文件外,你还需要使用 Whisper(fromFileURL:) 初始化器。你可以通过检查转录期间的控制台输出来验证 CoreML 是否处于活动状态。

将音频转换为 16kHz PCM 🔧

将音频帧导入 SwiftWhisper 的最简单方法是使用 AudioKit。以下示例获取一个输入音频文件,对其进行转换和重采样,并返回一个 16kHz PCM 浮点数数组。

import AudioKit

func convertAudioFileToPCMArray(fileURL: URL, completionHandler: @escaping (Result<[Float], Error>) -> Void) {
    var options = FormatConverter.Options()
    options.format = .wav
    options.sampleRate = 16000
    options.bitDepth = 16
    options.channels = 1
    options.isInterleaved = false

    let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
    let converter = FormatConverter(inputURL: fileURL, outputURL: tempURL, options: options)
    converter.start { error in
        if let error {
            completionHandler(.failure(error))
            return
        }

        let data = try! Data(contentsOf: tempURL) // Handle error here

        let floats = stride(from: 44, to: data.count, by: 2).map {
            return data[$0..<$0 + 2].withUnsafeBytes {
                let short = Int16(littleEndian: $0.load(as: Int16.self))
                return max(-1.0, min(Float(short) / 32767.0, 1.0))
            }
        }

        try? FileManager.default.removeItem(at: tempURL)

        completionHandler(.success(floats))
    }
}

提升开发速度 🚀

当为 Debug 构建配置编译你的应用程序时,你可能会发现转录性能很慢。这是因为编译器不会完全优化 SwiftWhisper,除非构建配置设置为 Release

你可以通过安装一个使用 .unsafeFlags(["-O3"]) 来强制最大优化的 SwiftWhisper 版本来解决这个问题。最简单的方法是使用 fast 分支上的最新提交。或者,你可以配置你的 scheme 以在 Release 配置中构建。

  ...
  dependencies: [
    // Using latest commit hash for `fast` branch:
    .package(url: "https://github.com/exPHAT/SwiftWhisper.git", revision: "deb1cb6a27256c7b01f5d3d2e7dc1dcc330b5d01"),
  ],
  ...