npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-native-webview-track-player

v1.0.2

Published

Headless audio player for building universal music apps in React Native.

Downloads

6

Readme

React Native WebView Track Player

React Native WebView Track Player is a headless audio player for building universal audio apps in React Native. It supports Android, iOS, Web, and Expo Go out-of-the-box. Using a WebView bridge, it aims to achieve similar functionality to react-native-track-player without requiring custom native code (see comparison table below).

Check out the example app for a full-fledged music player sample.

Contents

Comparison

| | react-native-track-player | expo-av | react-native-webview-track-player | | -------------------------- | ------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | Expo/Expo Go compatibility | ❌ | ✅ | ✅ | | Web compatibility | ❌ | ✅ | ✅ | | Background audio play | ✅ | ❌ (not without a build flag) | ✅ | | Lock-screen controls | ✅ | ❌ | ✅* (iOS & Web, no Android due to lack of MediaSession API) | | Built-in activity | ❌ | ❌ | ✅ | | True native bridge | ✅ | ✅ | ❌ |

From my experience, adopting a WebView bridge made audio playback a far more stable and consistent experience on iOS and especially Android. Plus, we gain seamless Web compatibility instead of the bundle splitting/conditional imports required when using react-native-track-player with React Native Web. That being said, a WebView bridge brings its own shortcomings (CORS with non-public URLs, HTML5 <audio> filetypes, etc.), so weigh in your own project needs carefully.

Highlights

  • Minimal core library, 1 file, ~600 SLOC.
  • 1 peer dependency, react-native-webview.
  • Expo Go, iOS Simulator, Web all work out-of-the-box with background audio and screen locking.
  • Render prop pattern over manually-exposed hooks (core manages all of the state/hooks for you, so you only need to provide the UI).
  • Track activity, plays, pauses, percentages listened, etc. are all automatically managed. A simple onActivity callback helps build analytics easily. By default, nothing is stored or transmitted.

Installation

Using your desired package manager (npm install, yarn add, bun add, etc.), add react-native-webview-track-player and its one required peer dependency react-native-webview to your project. Eg. with npm:

npm install react-native-webview-track-player react-native-webview --save

If you added react-native-webview for the first time, refer to its getting started guide if needed.

No assumptions are made on React/React Native versions or Expo SDKs. The latest of both should work without issue. As of current, the sample app is running on Expo SDK 49, React 18.2.0, React Native 0.72.6, and React Native WebView 13.6.3.

Usage

Here is a minimal working example:

import React from "react";
import { SafeAreaView, Text, Pressable } from "react-native";
import TrackPlayer, {
  type TrackPlayerRenderProps
} from "react-native-webview-track-player";

const playlist = [
  {
    id: "e8DPlI",
    title: "Modern",
    artist: "JM Galiè",
    audio: {
      url: "https://raw.githubusercontent.com/harismh/react-native-webview-track-player/main/.github/audio/sample.mp3"
    }
  }
];

const renderPlayer = ({ playerState, playPause }: TrackPlayerRenderProps) => (
  <SafeAreaView>
    <Pressable onPress={playPause}>
      <Text>{playerState.playing ? "Pause" : "Play"}</Text>
    </Pressable>

    <Text>Player State: {JSON.stringify(playerState)}</Text>
  </SafeAreaView>
);

const MinimalPlayer = () => (
  <TrackPlayer playlist={playlist} render={renderPlayer} />
);

export default MinimalPlayer;

There are many more props you can destructure or pass in to customize it further. See the example app in the repo for a fuller example.

Types

All type definitions are located in index.d.ts. The major types are:

| Type | Defn. | Optional? | Notes | | | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --- | | TrackPlayerProps.playlist | Array of PlaylistTrack | no | A minimal PlaylistTrack is {id: string, title: string, audio: { url: string }}. | | | TrackPlayerProps.render | Main render function | no | Callback receives TrackPlayerRenderProps. | | | TrackPlayerProps.activity | Map of track ids to PlaylistActivity | yes | Used to bootstrap and restore activity. Typically is used in conjunction with a back-end to serialize/restore user player state. | | | TrackPlayerProps.onActivity | Callback for any activity in the player | yes | Can be used to build analytics/reporting. Passed-in arg to callback is Activity. | | | TrackPlayerProps.config | TrackPlayerConfig | yes | Any config keys not passed-in will fallback to defaults. | | | TrackPlayerConfig | {audioElementId: string, playerIndexKey: string, webViewPostMessageIntervalMs: number, activityIntervalMs: number, finishedTrackPercentageThreshold: number} | yes | Defaults: { audioElementId: 'rnwv_audio', playerIndexKey: 'rnwv_player_index', webViewPostMessageIntervalMs: 1000, activityIntervalMs: 20000, finishedTrackPercentageThreshold: 90 }. audioElementId or playerIndexKey should be changed only if there are any conflicts with the defaults. webViewPostMessageIntervalMs is the setInterval time between RN and the WebView. Times <=1 second work best for rendering. activityIntervalMs sets up how often onActivity gets called (activityState from render props gets updated continuously. onActivity is meant to be used as auto-debounced async/reporting calls. If you need no delay, reference activityState directly.)finishedTrackPercentageThreshold is a number between 1-99 and is used to decide whether to send the finishedTrack activity to onActivity. | | | TrackPlayerRenderProps.PlayerState | { playing: ?boolean, currentTime: ?number, duration: ?number, trackIndex: number, playbackRate: 1 \| 1.5 \| 2 \| 0.5 } | -- | <TrackPlayer/> loads each audio in the playlist lazily to reduce bandwidth. Prior to loading audio, playing, currentTime, duration are all null. So, your UI will need to guard against them. | | | TrackPlayerRenderProps.ActivityState | ?{ [trackId: string]: ?{ lastPositionSecs: number, totalListenedSecs: number, percentageListened: number, secToListened?: { [sec: number]: true/false }}} | -- | If a track is never played, activity map will be undefined until first played. secToListened is largely a bookkeeping prop used to create scrub-proof percentages. onActivity always receives secToListened as undefined to reduce prop size. | | | TrackPlayerRenderProps.playPause | () => void; | -- | Sets current track to pause/play. Calls onActivity if set. | | | TrackPlayerRenderProps.next | () => void; | -- | Skips to next track. Guards against index out of bounds automatically. | | | TrackPlayerRenderProps.previous | () => void; | -- | Skips to previous track. Guards against index out of bounds automatically. | | | TrackPlayerRenderProps.seekTrack | (trackIndex: number) => void; | -- | Skips to the index provided. Does not guard currently. | | | TrackPlayerRenderProps.scrubTo | (seconds: number) => void; | -- | Skips to time provided in current track. Does not guard currently. | | | TrackPlayerRenderProps.setPlaybackRate | (playbackSpeed: 1 | 0.5 | 1.5 | 2 ) => void; | -- | Sets the provided playback speed to the current track. | |

Contributing

I consider the library as feature-complete and stable as it fulfills my own needs. Pull requests and forks are welcome, though. Refer to CONTRIBUTING.md for development commands.

License

Copyright (c) harismh MIT.

Initial template bootstrapped with create-react-native-library.