Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.0 ios #301

Merged
merged 12 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions binding/ios/Leopard-iOS.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = 'Leopard-iOS'
s.module_name = 'Leopard'
s.version = '1.2.0'
s.version = '2.0.0'
s.license = {:type => 'Apache 2.0'}
s.summary = 'iOS SDK for Picovoice\'s Leopard speech-to-text engine.'
s.description =
Expand All @@ -23,8 +23,8 @@ Pod::Spec.new do |s|
DESC
s.homepage = 'https://github.com/Picovoice/leopard/tree/master/binding/ios'
s.author = { 'Picovoice' => '[email protected]' }
s.source = { :git => "https://github.com/Picovoice/leopard.git", :tag => "Leopard-iOS-v1.2.0" }
s.ios.deployment_target = '11.0'
s.source = { :git => "https://github.com/Picovoice/leopard.git", :tag => "Leopard-iOS-v2.0.0" }
s.ios.deployment_target = '13.0'
s.swift_version = '5.0'
s.vendored_frameworks = 'lib/ios/PvLeopard.xcframework'
s.source_files = 'binding/ios/*.{swift}'
Expand Down
125 changes: 91 additions & 34 deletions binding/ios/Leopard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,32 @@ public struct LeopardWord {
/// Transcription confidence. It is a number within [0, 1].
public let confidence: Float

/// The speaker tag is `-1` if diarization is not enabled during initialization;
/// otherwise, it's a non-negative integer identifying unique speakers, with `0` reserved for
/// unknown speakers.
public let speakerTag: Int

/// Constructor.
///
/// - Parameters:
/// - word: Transcribed word.
/// - startSec: Start of word in seconds.
/// - endSec: End of word in seconds.
/// - confidence: Transcription confidence. It is a number within [0, 1].
public init(word: String, startSec: Float, endSec: Float, confidence: Float) {
/// - speakerTag: The speaker tag is `-1` if diarization is not enabled during initialization;
/// otherwise, it's a non-negative integer identifying unique speakers, with `0` reserved for
/// unknown speakers.
public init(
word: String,
startSec: Float,
endSec: Float,
confidence: Float,
speakerTag: Int) {
self.word = word
self.startSec = startSec
self.endSec = endSec
self.confidence = confidence
self.speakerTag = speakerTag
}
}

Expand All @@ -57,15 +71,27 @@ public class Leopard {

public static let sampleRate = UInt32(pv_sample_rate())
public static let version = String(cString: pv_leopard_version())
private static var sdk = "ios"

public static func setSdk(sdk: String) {
self.sdk = sdk
}

/// Constructor.
///
/// - Parameters:
/// - accessKey: The AccessKey obtained from Picovoice Console (https://console.picovoice.ai).
/// - modelPath: Absolute path to file containing model parameters.
/// - enableAutomaticPunctuation: Set to `true` to enable automatic punctuation insertion.
/// - enableDiarization: Set to `true` to enable speaker diarization, which allows Leopard to
/// differentiate speakers as part of the transcription process. Word metadata will include
/// a `speakerTag` to identify unique speakers.
/// - Throws: LeopardError
public init(accessKey: String, modelPath: String, enableAutomaticPunctuation: Bool = false) throws {
public init(
accessKey: String,
modelPath: String,
enableAutomaticPunctuation: Bool = false,
enableDiarization: Bool = false) throws {

if accessKey.count == 0 {
throw LeopardInvalidArgumentError("AccessKey is required for Leopard initialization")
Expand All @@ -80,8 +106,15 @@ public class Leopard {
accessKey,
modelPathArg,
enableAutomaticPunctuation,
enableDiarization,
ksyeo1010 marked this conversation as resolved.
Show resolved Hide resolved
&handle)
try checkStatus(status, "Leopard init failed")

pv_set_sdk(Leopard.sdk)

if status != PV_STATUS_SUCCESS {
let messageStack = try getMessageStack()
throw pvStatusToLeopardError(status, "Leopard init failed", messageStack)
}
}

/// Constructor.
Expand All @@ -90,12 +123,20 @@ public class Leopard {
/// - accessKey: The AccessKey obtained from Picovoice Console (https://console.picovoice.ai).
/// - modelURL: URL to the file containing model parameters.
/// - enableAutomaticPunctuation: Set to `true` to enable automatic punctuation insertion.
/// - enableDiarization: Set to `true` to enable speaker diarization, which allows Leopard to
/// differentiate speakers as part of the transcription process. Word metadata will include
/// a `speakerTag` to identify unique speakers.
/// - Throws: LeopardError
public convenience init(accessKey: String, modelURL: URL, enableAutomaticPunctuation: Bool = false) throws {
public convenience init(
accessKey: String,
modelURL: URL,
enableAutomaticPunctuation: Bool = false,
enableDiarization: Bool = false) throws {
try self.init(
accessKey: accessKey,
modelPath: modelURL.path,
enableAutomaticPunctuation: enableAutomaticPunctuation)
enableAutomaticPunctuation: enableAutomaticPunctuation,
enableDiarization: enableDiarization)
}

deinit {
Expand Down Expand Up @@ -137,7 +178,10 @@ public class Leopard {
&cTranscript,
&numWords,
&cWords)
try checkStatus(status, "Leopard process failed")
if status != PV_STATUS_SUCCESS {
let messageStack = try getMessageStack()
throw pvStatusToLeopardError(status, "Leopard process failed", messageStack)
}

let transcript = String(cString: cTranscript!)
pv_leopard_transcript_delete(cTranscript)
Expand All @@ -149,7 +193,8 @@ public class Leopard {
word: String(cString: cWord.word),
startSec: Float(cWord.start_sec),
endSec: Float(cWord.end_sec),
confidence: Float(cWord.confidence)
confidence: Float(cWord.confidence),
speakerTag: Int(cWord.speaker_tag)
)
words.append(word)
}
Expand Down Expand Up @@ -185,15 +230,9 @@ public class Leopard {
&cTranscript,
&numWords,
&cWords)
do {
try checkStatus(status, "Leopard process failed")
} catch let error as LeopardInvalidArgumentError {
let fileExtension = (audioPath as NSString).pathExtension.lowercased()
if !Leopard.supportedAudioTypes.contains(fileExtension) {
throw LeopardInvalidArgumentError("Audio file with format '\(fileExtension)' is not supported")
} else {
throw error
}
if status != PV_STATUS_SUCCESS {
let messageStack = try getMessageStack()
throw pvStatusToLeopardError(status, "Leopard process file failed", messageStack)
}

let transcript = String(cString: cTranscript!)
Expand All @@ -206,7 +245,8 @@ public class Leopard {
word: String(cString: cWord.word),
startSec: Float(cWord.start_sec),
endSec: Float(cWord.end_sec),
confidence: Float(cWord.confidence)
confidence: Float(cWord.confidence),
speakerTag: Int(cWord.speaker_tag)
)
words.append(word)
}
Expand Down Expand Up @@ -248,37 +288,54 @@ public class Leopard {
"If this is a packaged asset, ensure you have added it to your xcode project.")
}

private func checkStatus(_ status: pv_status_t, _ message: String) throws {
if status == PV_STATUS_SUCCESS {
return
}

private func pvStatusToLeopardError(
_ status: pv_status_t,
_ message: String,
_ messageStack: [String] = []) -> LeopardError {
switch status {
case PV_STATUS_OUT_OF_MEMORY:
throw LeopardMemoryError(message)
return LeopardMemoryError(message, messageStack)
case PV_STATUS_IO_ERROR:
throw LeopardIOError(message)
return LeopardIOError(message, messageStack)
case PV_STATUS_INVALID_ARGUMENT:
throw LeopardInvalidArgumentError(message)
return LeopardInvalidArgumentError(message, messageStack)
case PV_STATUS_STOP_ITERATION:
throw LeopardStopIterationError(message)
return LeopardStopIterationError(message, messageStack)
case PV_STATUS_KEY_ERROR:
throw LeopardKeyError(message)
return LeopardKeyError(message, messageStack)
case PV_STATUS_INVALID_STATE:
throw LeopardInvalidStateError(message)
return LeopardInvalidStateError(message, messageStack)
case PV_STATUS_RUNTIME_ERROR:
throw LeopardRuntimeError(message)
return LeopardRuntimeError(message, messageStack)
case PV_STATUS_ACTIVATION_ERROR:
throw LeopardActivationError(message)
return LeopardActivationError(message, messageStack)
case PV_STATUS_ACTIVATION_LIMIT_REACHED:
throw LeopardActivationLimitError(message)
return LeopardActivationLimitError(message, messageStack)
case PV_STATUS_ACTIVATION_THROTTLED:
throw LeopardActivationThrottledError(message)
return LeopardActivationThrottledError(message, messageStack)
case PV_STATUS_ACTIVATION_REFUSED:
throw LeopardActivationRefusedError(message)
return LeopardActivationRefusedError(message, messageStack)
default:
let pvStatusString = String(cString: pv_status_to_string(status))
throw LeopardError("\(pvStatusString): \(message)")
return LeopardError("\(pvStatusString): \(message)", messageStack)
}
}

private func getMessageStack() throws -> [String] {
var messageStackRef: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?
var messageStackDepth: Int32 = 0
let status = pv_get_error_stack(&messageStackRef, &messageStackDepth)
if status != PV_STATUS_SUCCESS {
throw pvStatusToLeopardError(status, "Unable to get Leopard error state")
}

var messageStack: [String] = []
for i in 0..<messageStackDepth {
messageStack.append(String(cString: messageStackRef!.advanced(by: Int(i)).pointee!))
}

pv_free_error_stack(messageStackRef)

return messageStack
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -651,7 +651,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -673,6 +673,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -696,6 +697,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -719,6 +721,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -742,6 +745,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2022 Picovoice Inc.
// Copyright 2022-2023 Picovoice Inc.
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
Expand All @@ -9,9 +9,4 @@

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
}
}
class ViewController: UIViewController { }
Loading