Reorganized the Recording package target into folders.
This commit is contained in:
1 parent
fe08548b08
commit
aa9ec01611
19 files changed
+103
-112
No files matched your search
@@ -23,8 +23,6 @@
|
||||
membershipExceptions = (
|
||||
Attendi/Assets.xcassets,
|
||||
Attendi/AttendiApp.swift,
|
||||
Attendi/AudioRecordingService.swift,
|
||||
Attendi/AudioTranscribingService.swift,
|
||||
Attendi/ContentView.swift,
|
||||
);
|
||||
target = 02870A0C2FF7EB610079EA3A /* Attendi */;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-30
@@ -21,33 +21,3 @@ public protocol RecordingService: Sendable {
|
||||
func stop() async throws -> Data
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Services
|
||||
|
||||
/// The recording service used by default, which simulates the audio capture without touching a microphone.
|
||||
public struct SimulatedRecordingService: RecordingService {
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a simulated recording service.
|
||||
public init() {}
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
/// Simulates the start of an audio recording.
|
||||
public func start() async throws {}
|
||||
|
||||
/// Simulates the pause of an ongoing recording.
|
||||
public func pause() async throws {}
|
||||
|
||||
/// Simulates the resumption of a paused recording.
|
||||
public func resume() async throws {}
|
||||
|
||||
/// Simulates the stop of a recording.
|
||||
///
|
||||
/// - Returns: An empty audio payload.
|
||||
public func stop() async throws -> Data {
|
||||
.init()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import Foundation
|
||||
|
||||
/// A service that transcribes recorded audio into text for the Recording feature.
|
||||
///
|
||||
/// ``RecordingView`` attaches the service to its model at initialization, so the transcription can be swapped without touching the feature's
|
||||
/// state machine — for example, with a real transcription backend in the app, or with a fast mock in unit tests.
|
||||
public protocol TranscribingService: Sendable {
|
||||
|
||||
/// Transcribes the given recorded audio into text.
|
||||
///
|
||||
/// - Parameter audio: The recorded audio to transcribe.
|
||||
/// - Returns: The transcription of the recorded audio.
|
||||
func transcribe(_ audio: Data) async throws -> String
|
||||
|
||||
}
|
||||
+9
-9
@@ -1,13 +1,12 @@
|
||||
import AVFoundation
|
||||
import Recording
|
||||
|
||||
/// The recording service used by the Attendi sample app, which captures real audio from the device's microphone.
|
||||
/// The recording service that captures real audio from the device's microphone.
|
||||
///
|
||||
/// The service records into a temporary `.m4a` file through an `AVAudioRecorder`, and returns the file's contents when the recording stops.
|
||||
/// The user's permission to record is requested before a recording starts and, on the platforms that require it, the shared audio session is
|
||||
/// configured for recording while the capture is in progress.
|
||||
@MainActor
|
||||
final class AudioRecordingService: RecordingService {
|
||||
public final class AudioRecordingService: RecordingService {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
@@ -17,7 +16,7 @@ final class AudioRecordingService: RecordingService {
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates an audio recording service.
|
||||
init() {}
|
||||
public init() {}
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
@@ -26,7 +25,7 @@ final class AudioRecordingService: RecordingService {
|
||||
/// - Throws: ``AudioRecordingError/permissionNotGranted`` when the user denies the app access to the microphone,
|
||||
/// ``AudioRecordingError/captureNotStarted`` when the recorder fails to start, or any error thrown while configuring
|
||||
/// the audio session or creating the recorder.
|
||||
func start() async throws {
|
||||
public func start() async throws {
|
||||
guard await AVAudioApplication.requestRecordPermission() else {
|
||||
throw AudioRecordingError.permissionNotGranted
|
||||
}
|
||||
@@ -53,7 +52,7 @@ final class AudioRecordingService: RecordingService {
|
||||
/// Pauses the ongoing recording.
|
||||
///
|
||||
/// - Throws: ``AudioRecordingError/noOngoingRecording`` when no recording is in progress.
|
||||
func pause() async throws {
|
||||
public func pause() async throws {
|
||||
guard let recorder else {
|
||||
throw AudioRecordingError.noOngoingRecording
|
||||
}
|
||||
@@ -65,7 +64,7 @@ final class AudioRecordingService: RecordingService {
|
||||
///
|
||||
/// - Throws: ``AudioRecordingError/noOngoingRecording`` when no recording is in progress, or
|
||||
/// ``AudioRecordingError/captureNotStarted`` when the recorder fails to resume.
|
||||
func resume() async throws {
|
||||
public func resume() async throws {
|
||||
guard let recorder else {
|
||||
throw AudioRecordingError.noOngoingRecording
|
||||
}
|
||||
@@ -79,7 +78,7 @@ final class AudioRecordingService: RecordingService {
|
||||
/// - Returns: The audio captured since the recording started.
|
||||
/// - Throws: ``AudioRecordingError/noOngoingRecording`` when no recording is in progress, or any error thrown
|
||||
/// while reading the recorded audio file.
|
||||
func stop() async throws -> Data {
|
||||
public func stop() async throws -> Data {
|
||||
guard let recorder else {
|
||||
throw AudioRecordingError.noOngoingRecording
|
||||
}
|
||||
@@ -104,7 +103,7 @@ final class AudioRecordingService: RecordingService {
|
||||
// MARK: - Errors
|
||||
|
||||
/// The errors thrown by ``AudioRecordingService``.
|
||||
enum AudioRecordingError: Error {
|
||||
public enum AudioRecordingError: Error {
|
||||
/// The recorder failed to start or resume the audio capture.
|
||||
case captureNotStarted
|
||||
/// No recording is in progress.
|
||||
@@ -120,6 +119,7 @@ private enum Constant {
|
||||
/// The audio constants.
|
||||
enum Audio {
|
||||
/// The settings of the recorded audio: single-channel AAC at a 44.1 kHz sample rate, encoded in high quality.
|
||||
@MainActor
|
||||
static let settings: [String: Any] = [
|
||||
AVFormatIDKey: kAudioFormatMPEG4AAC,
|
||||
AVNumberOfChannelsKey: 1,
|
||||
+8
-9
@@ -1,18 +1,17 @@
|
||||
import AVFoundation
|
||||
import Recording
|
||||
import Speech
|
||||
|
||||
/// The transcribing service used by the Attendi sample app, which transcribes recorded audio into text on device.
|
||||
/// The transcribing service that transcribes recorded audio into text on device.
|
||||
///
|
||||
/// The service writes the recorded audio into a temporary `.m4a` file and runs it through a `SpeechAnalyzer` with a `SpeechTranscriber`
|
||||
/// module, joining the finalized results into the returned text. The speech model assets for the current locale are downloaded and installed
|
||||
/// on first use; every transcription after that happens entirely offline.
|
||||
struct AudioTranscribingService: TranscribingService {
|
||||
public struct AudioTranscribingService: TranscribingService {
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a speech transcribing service.
|
||||
init() {}
|
||||
/// Creates an audio transcribing service.
|
||||
public init() {}
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
@@ -22,7 +21,7 @@ struct AudioTranscribingService: TranscribingService {
|
||||
/// - Returns: The transcription of the recorded audio.
|
||||
/// - Throws: ``AudioTranscribingError/localeNotSupported`` when the transcriber does not support the current locale, or any
|
||||
/// error thrown while installing the speech model assets, reading the audio file, or analyzing its contents.
|
||||
func transcribe(_ audio: Data) async throws -> String {
|
||||
public func transcribe(_ audio: Data) async throws -> String {
|
||||
try audio.write(to: Constant.File.url)
|
||||
|
||||
defer {
|
||||
@@ -64,15 +63,15 @@ struct AudioTranscribingService: TranscribingService {
|
||||
// MARK: - Errors
|
||||
|
||||
/// The errors thrown by ``AudioTranscribingService``.
|
||||
enum AudioTranscribingError: Error {
|
||||
public enum AudioTranscribingError: Error {
|
||||
/// The transcriber does not support the current locale.
|
||||
case localeNotSupported
|
||||
}
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
/// The constant values used across the speech transcribing service.
|
||||
private nonisolated enum Constant {
|
||||
/// The constant values used across the audio transcribing service.
|
||||
private enum Constant {
|
||||
/// The file constants.
|
||||
enum File {
|
||||
/// The location of the temporary file the recorded audio is written into for the analysis.
|
||||
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
/// The recording service used for development, which simulates the audio capture without touching a microphone.
|
||||
///
|
||||
/// The service is internal on purpose: it only backs the feature's previews and the default values of its model, and is not part of the
|
||||
/// package's public interface.
|
||||
struct DummyRecordingService: RecordingService {
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
/// Simulates the start of an audio recording.
|
||||
func start() async throws {}
|
||||
|
||||
/// Simulates the pause of an ongoing recording.
|
||||
func pause() async throws {}
|
||||
|
||||
/// Simulates the resumption of a paused recording.
|
||||
func resume() async throws {}
|
||||
|
||||
/// Simulates the stop of a recording.
|
||||
///
|
||||
/// - Returns: An empty audio payload.
|
||||
func stop() async throws -> Data {
|
||||
.init()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import Foundation
|
||||
|
||||
/// The transcribing service used for development, which simulates the transcription work.
|
||||
///
|
||||
/// The service is internal on purpose: it only backs the feature's previews and the default values of its model, and is not part of the
|
||||
/// package's public interface.
|
||||
struct DummyTranscribingService: TranscribingService {
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
/// Simulates the transcription of the given recorded audio with a two-second delay.
|
||||
///
|
||||
/// - Parameter audio: The recorded audio to transcribe.
|
||||
/// - Returns: A dummy transcription.
|
||||
func transcribe(_ audio: Data) async throws -> String {
|
||||
try await Task.sleep(for: Constant.Delay.transcribing)
|
||||
|
||||
return Constant.Text.transcription
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
/// The constant values used across the transcribing services.
|
||||
private enum Constant {
|
||||
/// The delay constants.
|
||||
enum Delay {
|
||||
/// The duration of the simulated transcription work.
|
||||
static let transcribing: Duration = .seconds(2)
|
||||
}
|
||||
|
||||
/// The text constants.
|
||||
enum Text {
|
||||
/// The dummy transcription of a recorded audio.
|
||||
static let transcription = "This is a dummy transcription of the recorded audio."
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -1,56 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
/// A service that transcribes recorded audio into text for the Recording feature.
|
||||
///
|
||||
/// ``RecordingView`` attaches the service to its model at initialization, so the transcription can be swapped without touching the feature's
|
||||
/// state machine — for example, with a real transcription backend in the app, or with a fast mock in unit tests.
|
||||
public protocol TranscribingService: Sendable {
|
||||
|
||||
/// Transcribes the given recorded audio into text.
|
||||
///
|
||||
/// - Parameter audio: The recorded audio to transcribe.
|
||||
/// - Returns: The transcription of the recorded audio.
|
||||
func transcribe(_ audio: Data) async throws -> String
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Services
|
||||
|
||||
/// The transcribing service used by default, which simulates the transcription work.
|
||||
public struct SimulatedTranscribingService: TranscribingService {
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a simulated transcribing service.
|
||||
public init() {}
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
/// Simulates the transcription of the given recorded audio with a two-second delay.
|
||||
///
|
||||
/// - Parameter audio: The recorded audio to transcribe.
|
||||
/// - Returns: A dummy transcription.
|
||||
public func transcribe(_ audio: Data) async throws -> String {
|
||||
try await Task.sleep(for: Constant.Delay.transcribing)
|
||||
|
||||
return Constant.Text.transcription
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
/// The constant values used across the transcribing services.
|
||||
private enum Constant {
|
||||
/// The delay constants.
|
||||
enum Delay {
|
||||
/// The duration of the simulated transcription work.
|
||||
static let transcribing: Duration = .seconds(2)
|
||||
}
|
||||
|
||||
/// The text constants.
|
||||
enum Text {
|
||||
/// The dummy transcription of a recorded audio.
|
||||
static let transcription = "This is a dummy transcription of the recorded audio."
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -40,11 +40,11 @@ extension RecordingView {
|
||||
/// Creates a model attached to the given recording and transcribing services.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - recorder: The service that captures the audio from a microphone. Defaults to ``SimulatedRecordingService``.
|
||||
/// - transcriber: The service that transcribes the recorded audio into text. Defaults to ``SimulatedTranscribingService``.
|
||||
/// - recorder: The service that captures the audio from a microphone. Defaults to ``DummyRecordingService``.
|
||||
/// - transcriber: The service that transcribes the recorded audio into text. Defaults to ``DummyTranscribingService``.
|
||||
init(
|
||||
recorder: any RecordingService = SimulatedRecordingService(),
|
||||
transcriber: any TranscribingService = SimulatedTranscribingService()
|
||||
recorder: any RecordingService = DummyRecordingService(),
|
||||
transcriber: any TranscribingService = DummyTranscribingService()
|
||||
) {
|
||||
self.recorder = recorder
|
||||
self.transcriber = transcriber
|
||||
+2
-2
@@ -123,7 +123,7 @@ private enum Constant {
|
||||
"Recording view"
|
||||
) {
|
||||
RecordingView(
|
||||
recorder: SimulatedRecordingService(),
|
||||
transcriber: SimulatedTranscribingService()
|
||||
recorder: DummyRecordingService(),
|
||||
transcriber: DummyTranscribingService()
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user