Documentation Index
Fetch the complete documentation index at: https://mintlify.com/rive-app/rive-ios/llms.txt
Use this file to discover all available pages before exploring further.
The Rive iOS Runtime provides built-in audio support for Rive files with audio assets. You can control the playback volume for animations with embedded or referenced audio.
Overview
Rive animations can include audio assets that play during animation playback. The iOS Runtime allows you to adjust the volume of these audio assets through the volume property on RiveModel and RiveArtboard.
Volume Property
The volume is controlled through a Float property with a range typically from 0.0 (muted) to 1.0 (full volume):
import RiveRuntime
let riveModel = try RiveModel(fileName: "animation_with_audio")
// Set volume (0.0 = muted, 1.0 = full volume)
riveModel.volume = 0.5
Default Volume
The runtime defaults to full volume (1.0) when no volume is explicitly set:
// Default volume is 1.0
let model = try RiveModel(fileName: "audio_file")
print(model.volume) // Prints: 1.0
Setting Volume with RiveModel
The RiveModel class provides a volume property:
import RiveRuntime
class AudioController {
let riveModel: RiveModel
init() {
riveModel = try! RiveModel(fileName: "lip_sync_test")
try? riveModel.setArtboard()
try? riveModel.setStateMachine("State Machine 1")
}
func setVolume(_ volume: Float) {
// Volume range: 0.0 (muted) to 1.0 (full)
riveModel.volume = volume
}
func mute() {
riveModel.volume = 0.0
}
func unmute() {
riveModel.volume = 1.0
}
}
Volume with RiveViewModel (SwiftUI)
For SwiftUI applications using RiveViewModel:
import SwiftUI
import RiveRuntime
struct AudioView: View {
@StateObject private var riveViewModel = RiveViewModel(
fileName: "lip-sync_test",
stateMachineName: "State Machine 1",
artboardName: "Lip_sync_2"
)
@State private var volume: Float = 1.0
var body: some View {
VStack {
riveViewModel.view()
VStack {
Text("Volume: \(Int(volume * 100))%")
Slider(value: $volume, in: 0...1) { _ in
riveViewModel.riveModel?.volume = volume
}
}
.padding()
}
.onAppear {
// Set initial volume
riveViewModel.riveModel?.volume = volume
}
}
}
Complete SwiftUI Example
import SwiftUI
import RiveRuntime
struct AudioControlView: View {
@StateObject private var riveViewModel = RiveViewModel(
fileName: "lip-sync_test",
stateMachineName: "State Machine 1",
artboardName: "Lip_sync_2"
)
@State private var volume: Double = 1.0
@State private var isMuted: Bool = false
var body: some View {
VStack(spacing: 20) {
// Rive animation
riveViewModel.view()
.frame(height: 400)
// Volume controls
VStack(spacing: 15) {
HStack {
Image(systemName: "speaker.fill")
Slider(value: $volume, in: 0...1) { editing in
if !editing {
updateVolume()
}
}
.disabled(isMuted)
Image(systemName: "speaker.wave.3.fill")
}
HStack(spacing: 20) {
Button(isMuted ? "Unmute" : "Mute") {
toggleMute()
}
Text("Volume: \(Int(isMuted ? 0 : volume * 100))%")
.font(.caption)
.foregroundColor(.gray)
}
}
.padding()
}
.onAppear {
riveViewModel.riveModel?.volume = Float(volume)
}
}
private func updateVolume() {
riveViewModel.riveModel?.volume = Float(volume)
}
private func toggleMute() {
isMuted.toggle()
riveViewModel.riveModel?.volume = isMuted ? 0.0 : Float(volume)
}
}
UIKit Example
import UIKit
import RiveRuntime
class AudioViewController: UIViewController {
@IBOutlet weak var riveView: RiveView!
@IBOutlet weak var volumeSlider: UISlider!
@IBOutlet weak var muteButton: UIButton!
private var riveModel: RiveModel!
private var isMuted = false
private var savedVolume: Float = 1.0
override func viewDidLoad() {
super.viewDidLoad()
// Initialize Rive model
riveModel = try! RiveModel(fileName: "audio_animation")
try? riveModel.setArtboard()
try? riveModel.setStateMachine()
// Set up view
riveView.setModel(riveModel)
// Configure slider
volumeSlider.minimumValue = 0.0
volumeSlider.maximumValue = 1.0
volumeSlider.value = 1.0
// Set initial volume
riveModel.volume = 1.0
}
@IBAction func volumeSliderChanged(_ slider: UISlider) {
let volume = slider.value
riveModel.volume = volume
savedVolume = volume
if volume == 0 {
isMuted = true
updateMuteButton()
} else if isMuted {
isMuted = false
updateMuteButton()
}
}
@IBAction func muteButtonTapped(_ sender: UIButton) {
isMuted.toggle()
if isMuted {
savedVolume = riveModel.volume
riveModel.volume = 0.0
volumeSlider.value = 0.0
} else {
riveModel.volume = savedVolume
volumeSlider.value = savedVolume
}
updateMuteButton()
}
private func updateMuteButton() {
let title = isMuted ? "Unmute" : "Mute"
muteButton.setTitle(title, for: .normal)
}
}
Volume Persistence
The RiveModel stores the volume value internally. When you set an artboard, the stored volume is applied:
let model = try RiveModel(fileName: "audio_file")
// Set volume before artboard
model.volume = 0.5
// Volume persists when setting artboard
try model.setArtboard()
print(model.volume) // Prints: 0.5
If no artboard is set, the model stores the volume and applies it when an artboard is configured.
Artboard-Level Volume Control
You can also control volume directly on the artboard:
import RiveRuntime
let artboard = try riveFile.artboard()
artboard.volume = 0.3 // Note: In Swift this is accessed as __volume
In Swift, the property is refined and typically accessed through RiveModel.
Volume Range
While the typical range is 0.0 to 1.0:
0.0 = Completely muted
0.5 = Half volume
1.0 = Full volume (default)
Values outside this range are typically clamped by the audio system.
Best Practices
- Set Volume Early: Configure volume before or immediately after loading the Rive file
- Save User Preferences: Persist volume settings using
UserDefaults or similar
- Respect System Volume: The Rive volume is relative to the system volume
- Provide UI Controls: Give users slider controls for fine-tuned volume adjustment
- Mute State: Implement separate mute functionality rather than just setting volume to 0
- Initial Volume: Consider starting with a lower volume (e.g., 0.5) to avoid startling users
Common Patterns
Volume Presets
enum VolumePreset: Float {
case muted = 0.0
case low = 0.25
case medium = 0.5
case high = 0.75
case full = 1.0
}
riveModel.volume = VolumePreset.medium.rawValue
Fade In/Out
func fadeOut(duration: TimeInterval = 1.0) {
let startVolume = riveModel.volume
let steps = 20
let delay = duration / Double(steps)
for i in 0...steps {
DispatchQueue.main.asyncAfter(deadline: .now() + delay * Double(i)) {
let progress = Float(i) / Float(steps)
self.riveModel.volume = startVolume * (1.0 - progress)
}
}
}
Volume Persistence
class AudioSettings {
private let volumeKey = "riveAudioVolume"
var volume: Float {
get {
UserDefaults.standard.float(forKey: volumeKey)
}
set {
UserDefaults.standard.set(newValue, forKey: volumeKey)
}
}
func apply(to model: RiveModel) {
model.volume = volume
}
}
Troubleshooting
Audio Not Playing
- Verify the Rive file contains audio assets
- Check that volume is not set to 0.0
- Ensure device volume is not muted
- Verify audio session is configured correctly
Volume Changes Not Taking Effect
- Set volume after the artboard is loaded
- Access volume through
RiveModel rather than artboard directly
- Ensure you’re modifying the correct model instance
Audio Session Configuration
For proper audio playback, configure your app’s audio session:
import AVFoundation
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Failed to set audio session: \(error)")
}
See Also