Podli ポッドキャストプレーヤー
Webplayer
العربية Български Čeština Dansk Deutsch Ελληνικά English Español Suomi Filipino Français עברית हिन्दी Magyar Indonesia Italiano 日本語 한국어 Melayu Nederlands Norsk Polski Português (BR) Português Română Русский Slovenčina Svenska ไทย Türkçe Українська Tiếng Việt 简体中文 繁體中文
ネジネジ低空飛行 — ゆるバイポーラー thinking aloud —
Podliアプリで聴く 🎧
お気に入りの番組をフォローして、オフラインでも車内でもCarPlayやAndroid Autoで再生。いつでも続きから聴けます。無料でお試しできます。
万歩計ならぬ、ことばの歩数計アプリ開発案をモジモジと語るのみ。誰か一緒にやってくれないかなー? import AVFoundation import Foundation // MARK: - 発話時間計測クラス (Local-only VAD Engine) class SpeechActivityTracker: NSObject, ObservableObject { private let audioEngine = AVAudioEngine() @Published var totalSpeechSeconds: Double = 0.0 @Published var isSpeaking: Bool = false // 音量しきい値 (環境に合わせて調整) private let speechThreshold: Float = -30.0 func startMonitoring() { let inputNode = audioEngine.inputNode let recordingFormat = inputNode.outputFormat(forBus: 0) // 端末ローカルでマイク入力をキャプチャ (録音データは保存・送信せず即時破棄) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self] buffer, _ in guard let self = self else { return } // 音量(RMS)の計算 guard let channelData = buffer.floatChannelData?[0] else { return } let channelDataValue = Array(UnsafeBufferPointer(start: channelData, count: Int(buffer.frameLength))) var sum: Float = 0.0 for sample in channelDataValue { sum += sample * sample } let rms = sqrt(sum / Float(buffer.frameLength)) let avgPower = 20 * log10(rms) // dB単位 // 判定処理 DispatchQueue.main.async { if avgPower > self.speechThreshold { self.isSpeaking = true // バッファの長さ分(約0.02秒)を発話時間に加算 let duration = Double(buffer.frameLength) / recordingFormat.sampleRate self.totalSpeechSeconds += duration } else { self.isSpeaking = false } } } do { try audioEngine.start() } catch { print("AudioEngine起動エラー: \(error.localizedDescription)") } } func stopMonitoring() { audioEngine.inputNode.removeTap(onBus: 0) audioEngine.stop() } }
エピソード: ネジネジ低空飛行 — ゆるバイポーラー thinking aloud —
Podli 無料のPodliアプリを入手
↓ App