Skip to content

Latest commit

 

History

History
121 lines (92 loc) · 3.14 KB

File metadata and controls

121 lines (92 loc) · 3.14 KB

SmartSpeedKit

SmartSpeedKit is a Swift package for seekable, offline smart-speed playback of spoken-word audio.

It provides:

  • A timeline model (SmartSpeedAnalysis) that marks compressible gaps.
  • Segment generation (SegmentBuilder) that assigns different playback rates to speech vs gaps.
  • A seekable AVAudioEngine-based player (SeekableSmartSpeedPlayer).
  • Optional voice enhancement (EQ + dynamics processor).
  • Bidirectional timeline mapping (SmartSpeedTimeMapper) for progress UI and scrubbing.

Requirements

  • iOS 15+
  • macOS 12+
  • Swift Package Manager

Installation

Add this package to your Package.swift dependencies and target dependencies.

// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "YourApp",
    platforms: [
        .iOS(.v15),
        .macOS(.v12)
    ],
    dependencies: [
        .package(url: "https://github.com/<your-org>/SmartSpeedKit.git", branch: "main")
    ],
    targets: [
        .target(
            name: "YourApp",
            dependencies: ["SmartSpeedKit"]
        )
    ]
)

Core Types

  • CompressibleGap: start/end interval in original timeline seconds.
  • SmartSpeedAnalysis: total duration + ordered list of CompressibleGap values.
  • PlaybackSegment: frame-range + playback rate for one scheduled segment.
  • SegmentBuilder: creates PlaybackSegment values from an audio file + analysis.
  • SeekableSmartSpeedPlayer: engine-backed player with play/pause/stop/seek.
  • VoiceEnhancementChain: optional spoken-word EQ + dynamics processing.
  • SmartSpeedTimeMapper: convert between original time and elapsed smart-speed time.

Quick Start

import AVFoundation
import SmartSpeedKit

let url = URL(fileURLWithPath: "/path/to/audio.m4a")
let file = try AVAudioFile(forReading: url)

// Build or load your analysis from a detector in your app.
let analysis = SmartSpeedAnalysis(
    duration: 1800,
    gaps: [
        .init(start: 12.4, end: 12.9),
        .init(start: 47.2, end: 48.0)
    ]
)

let player = SeekableSmartSpeedPlayer()
player.speechRate = 1.1
player.gapRate = 2.4

try player.prepare()
player.load(file: file, analysis: analysis)
player.play()

// Later...
player.seek(to: 300) // original timeline seconds

Optional Voice Enhancement

try await player.enableVoiceEnhancement()

This inserts:

  • AVAudioUnitEQ (spoken-word preset)
  • kAudioUnitSubType_DynamicsProcessor (spoken-word dynamics preset)

Use this after prepare() and before playback (or while stopped).

Timeline Mapping

When smart-speed is active, elapsed playback time diverges from original timeline time. Use the mapper for UI progress and scrubbing:

if let mapper = player.makeTimeMapper() {
    let elapsed = mapper.elapsedTime(forOriginalTime: 600)
    let original = mapper.originalTime(forElapsedTime: elapsed)
    print(elapsed, original)
}

Notes

  • SmartSpeedKit expects you to provide SmartSpeedAnalysis (gap detection is app-specific).
  • Gap intervals should be sorted and non-overlapping for best results.
  • All times are in seconds; playback scheduling is frame-based.

Testing

Run package tests:

swift test