Files
voicediary/VoiceDiary/Services/AudioRecorderService.swift
Felix Förtsch dca03214b0 initial VoiceDiary iOS app setup
SwiftUI + SwiftData + iCloud, Apple Speech transcription (German),
audio recording, summarization service protocol (LLM-ready),
localization scaffolding (EN/DE/ES/FR), basic tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:57:41 +01:00

73 lines
1.9 KiB
Swift

import AVFoundation
import Foundation
@Observable
final class AudioRecorderService: NSObject {
var isRecording = false
var recordingDuration: TimeInterval = 0
private var audioRecorder: AVAudioRecorder?
private var timer: Timer?
private var startTime: Date?
func startRecording() throws -> URL {
let session = AVAudioSession.sharedInstance()
try session.setCategory(.record, mode: .default)
try session.setActive(true)
let fileName = "memo-\(Date.now.ISO8601Format()).m4a"
.replacingOccurrences(of: ":", with: "-")
let url = VoiceMemo.audioDirectory.appendingPathComponent(fileName)
let settings: [String: Any] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
]
audioRecorder = try AVAudioRecorder(url: url, settings: settings)
audioRecorder?.delegate = self
audioRecorder?.record()
isRecording = true
recordingDuration = 0
startTime = .now
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
guard let self, let startTime = self.startTime else { return }
self.recordingDuration = Date.now.timeIntervalSince(startTime)
}
return url
}
func stopRecording() -> (url: URL, duration: TimeInterval)? {
guard let recorder = audioRecorder else { return nil }
let url = recorder.url
let duration = recorder.currentTime
recorder.stop()
timer?.invalidate()
timer = nil
audioRecorder = nil
isRecording = false
startTime = nil
try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
return (url, duration)
}
}
extension AudioRecorderService: AVAudioRecorderDelegate {
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
isRecording = false
timer?.invalidate()
timer = nil
}
}
}