Problem
When "Store Audio on Phone" is enabled, local WAL files are kept on device but NOT used for playback. The app always streams audio from the cloud (GCS), even when a local copy exists.
Current behavior:
// app/lib/widgets/conversation_audio_player_widget.dart
final urls = getConversationAudioUrls(
conversationId: widget.conversation.id,
audioFileIds: audioFileIds,
format: 'wav',
);
// Always generates: v1/sync/audio/{conversationId}/{audioFileId}?format=wav
// Always streams from GCS
Why this is wasteful:
- Downloads same audio multiple times if replayed
- Wastes bandwidth and cloud egress costs
- Doesn't work offline (even though local file exists)
- "Store Audio on Phone" setting has no playback benefit
Proposed Solution
Check for local WAL files first, fall back to cloud streaming if missing.
Playback flow:
Click play → Check if WAL exists locally
→ If yes: Play from local file (instant, offline-capable)
→ If no: Stream from cloud (current behavior)
Benefits:
- Save bandwidth for users
- Reduce cloud egress costs for Omi
- Offline playback when local copy exists
- Instant playback (no network latency)
- "Store Audio on Phone" setting becomes actually useful for playback
Implementation
1. Add local file check in audio API:
// app/lib/backend/http/api/audio.dart
Future<List<String>> getConversationAudioUrls({
required String conversationId,
required List<String> audioFileIds,
String format = 'wav',
}) async {
List<String> urls = [];
for (String audioFileId in audioFileIds) {
// Check if local WAL file exists
String? localPath = await getLocalWalPath(conversationId, audioFileId);
if (localPath != null && await File(localPath).exists()) {
// Use local file
urls.add('file://$localPath');
} else {
// Fall back to cloud streaming
urls.add(getAudioStreamUrl(
conversationId: conversationId,
audioFileId: audioFileId,
format: format,
));
}
}
return urls;
}
2. Helper to locate WAL files:
Future<String?> getLocalWalPath(String conversationId, String audioFileId) async {
if (!SharedPreferencesUtil().unlimitedLocalStorageEnabled) {
return null; // Only use local files when setting is enabled
}
// Look up WAL directory and check for matching file
// Return path if exists, null otherwise
}
3. Audio player already supports file:// URIs:
just_audio package handles both HTTP and local file URIs
- No changes needed in
conversation_audio_player_widget.dart
Edge Cases
What if local file is corrupt/incomplete?
- Catch playback errors
- Fall back to cloud streaming
- Optionally delete corrupt local file
What if user disables "Store Audio on Phone"?
- Only check local files when
unlimitedLocalStorageEnabled == true
- Otherwise skip local check (current cloud-only behavior)
What if file format differs?
- WAL files are Opus, playback uses WAV
- Either: transcode on-the-fly (heavy)
- Or: also store WAV locally when syncing
- Or: update player to support Opus directly (most efficient)
Alternative: Smart caching
Instead of requiring "Store Audio on Phone" to be enabled, implement automatic caching:
- Download played audio to cache directory
- Expire after N days or when storage fills
- Transparent to user (no setting required)
- Similar to how images/videos are cached
Related Code
- Audio player:
app/lib/widgets/conversation_audio_player_widget.dart
- Audio API:
app/lib/backend/http/api/audio.dart
- WAL sync:
app/lib/services/wals/local_wal_sync.dart
- Preferences:
app/lib/backend/preferences.dart (line 336: unlimitedLocalStorageEnabled)
- Capture provider:
app/lib/providers/capture_provider.dart (line 580: WAL condition)
Requested by: l4w1 (Discord user 261726922696818689)
Context: Discord #general-vector-chat, 2026-03-30
Problem
When "Store Audio on Phone" is enabled, local WAL files are kept on device but NOT used for playback. The app always streams audio from the cloud (GCS), even when a local copy exists.
Current behavior:
Why this is wasteful:
Proposed Solution
Check for local WAL files first, fall back to cloud streaming if missing.
Playback flow:
Benefits:
Implementation
1. Add local file check in audio API:
2. Helper to locate WAL files:
3. Audio player already supports file:// URIs:
just_audiopackage handles both HTTP and local file URIsconversation_audio_player_widget.dartEdge Cases
What if local file is corrupt/incomplete?
What if user disables "Store Audio on Phone"?
unlimitedLocalStorageEnabled == trueWhat if file format differs?
Alternative: Smart caching
Instead of requiring "Store Audio on Phone" to be enabled, implement automatic caching:
Related Code
app/lib/widgets/conversation_audio_player_widget.dartapp/lib/backend/http/api/audio.dartapp/lib/services/wals/local_wal_sync.dartapp/lib/backend/preferences.dart(line 336:unlimitedLocalStorageEnabled)app/lib/providers/capture_provider.dart(line 580: WAL condition)Requested by: l4w1 (Discord user 261726922696818689)
Context: Discord #general-vector-chat, 2026-03-30