Skip to content

silvermine/tauri-plugin-audio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tauri Plugin Audio

CI

Headless, state-driven audio playback API for Tauri 2.x apps with native transport control integration.

This plugin provides a cross-platform audio playback interface with transport controls (play, pause, stop, seek), volume/rate settings, and OS media integration (lock screen, notification shade, headphone controls). It is designed to be wrapped by a consuming app's own API layer.

Features

  • State-machine-driven playback with type-safe action gating
  • OS transport control integration via metadata (title, artist, artwork)
  • Real-time state change events (status, time, volume, etc.)
  • Volume, mute, playback rate, and loop controls
  • Cross-platform support (Windows, iOS, Android)
Platform Supported
Windows Planned
macOS Planned
Android Planned
iOS Planned

Getting Started

Installation

  1. Install NPM dependencies:

    npm install
  2. Build the TypeScript bindings:

    npm run build
  3. Build the Rust plugin:

    cargo build

Tests

Run all tests (TypeScript and Rust):

npm test

Run TypeScript tests only:

npm run test:ts

Run Rust tests only:

cargo test --workspace --lib

Install

This plugin requires a Rust version of at least 1.89

Rust

Add the plugin to your Cargo.toml:

src-tauri/Cargo.toml

[dependencies]
tauri-plugin-audio = { git = "https://github.com/silvermine/tauri-plugin-audio" }

JavaScript/TypeScript

Install the JavaScript bindings:

npm install @silvermine/tauri-plugin-audio

Usage

Prerequisites

Initialize the plugin in your tauri::Builder:

fn main() {
   tauri::Builder::default()
      .plugin(tauri_plugin_audio::init())
      .run(tauri::generate_context!())
      .expect("error while running tauri application");
}

API

Get the player

import { getPlayer, PlaybackStatus } from '@silvermine/tauri-plugin-audio';

async function checkPlayer() {
   const player = await getPlayer();

   console.debug(`Status: ${player.status}, Time: ${player.currentTime}`);
}

Load, play, pause, stop, or seek

The API uses discriminated unions with type guards for compile-time safety. Only valid transport actions are available based on the player's status.

import {
   getPlayer, PlaybackStatus, hasAction, AudioAction,
} from '@silvermine/tauri-plugin-audio';

async function loadAndPlay() {
   const player = await getPlayer();

   if (player.status === PlaybackStatus.Idle) {
      const { player: ready } = await player.load(
         'https://example.com/song.mp3',
         {
            title: 'My Song',
            artist: 'Artist Name',
            artwork: 'https://example.com/cover.jpg',
         },
      );

      await ready.play();
   }
}

async function managePlayback() {
   const player = await getPlayer();

   if (hasAction(player, AudioAction.Pause)) {
      await player.pause();
   } else if (hasAction(player, AudioAction.Play)) {
      await player.play();
   }
}

Adjust settings

Volume, mute, playback rate, and loop controls are always available regardless of playback status.

import { getPlayer } from '@silvermine/tauri-plugin-audio';

async function adjustSettings() {
   const player = await getPlayer();

   await player.setVolume(0.5);
   await player.setMuted(false);
   await player.setPlaybackRate(1.5);
   await player.setLoop(true);
}

Listen for state changes

listen receives updates for state transitions (status changes, volume, settings, errors).

import { getPlayer, PlaybackStatus } from '@silvermine/tauri-plugin-audio';

async function watchPlayback() {
   const player = await getPlayer();

   const unlisten = await player.listen((updated) => {
      console.debug(`Status: ${updated.status}`);

      if (updated.status === PlaybackStatus.Ended) {
         console.debug('Playback finished');
      }
   });

   // To stop listening:
   unlisten();
}

Listen for time updates

onTimeUpdate receives lightweight, high-frequency updates (~250ms) carrying only currentTime and duration, avoiding the overhead of serializing the full player state on every tick.

import { getPlayer } from '@silvermine/tauri-plugin-audio';

async function trackProgress() {
   const player = await getPlayer();

   const unlisten = await player.onTimeUpdate((time) => {
      const pct = time.duration > 0
         ? (time.currentTime / time.duration) * 100
         : 0;

      console.debug(`${time.currentTime}s / ${time.duration}s (${pct.toFixed(1)}%)`);
   });

   // To stop listening:
   unlisten();
}

State Machine

The player follows a state machine where transport actions are gated by the current PlaybackStatus:

Status Allowed Actions
Idle load
Loading stop
Ready play, seek, stop
Playing pause, seek, stop
Paused play, seek, stop
Ended play, seek, load, stop
Error load

Settings (setVolume, setMuted, setPlaybackRate, setLoop), listen, and onTimeUpdate are always available regardless of status.

Development Standards

This project follows the Silvermine standardization guidelines. Key standards include:

  • EditorConfig: Consistent editor settings across the team
  • Markdownlint: Markdown linting for documentation
  • Commitlint: Conventional commit message format
  • Code Style: 3-space indentation, LF line endings

Running Standards Checks

npm run standards

License

MIT

Contributing

Contributions are welcome! Please follow the established coding standards and commit message conventions.

About

Native audio playback

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors