diff --git a/materialious/android/app/capacitor.build.gradle b/materialious/android/app/capacitor.build.gradle
index 76030400..e874b5b5 100644
--- a/materialious/android/app/capacitor.build.gradle
+++ b/materialious/android/app/capacitor.build.gradle
@@ -12,6 +12,7 @@ dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-browser')
implementation project(':capgo-inappbrowser')
+ implementation project(':mediagrid-capacitor-native-audio')
implementation project(':capacitor-nodejs')
}
diff --git a/materialious/android/app/src/main/AndroidManifest.xml b/materialious/android/app/src/main/AndroidManifest.xml
index 7cbefaa0..cd74452b 100644
--- a/materialious/android/app/src/main/AndroidManifest.xml
+++ b/materialious/android/app/src/main/AndroidManifest.xml
@@ -34,9 +34,23 @@
android:grantUriPermissions="true">
+
+
+
+
+
+
+
+
+
+
diff --git a/materialious/android/app/src/main/res/values/strings.xml b/materialious/android/app/src/main/res/values/strings.xml
index a2310dac..f9764d40 100644
--- a/materialious/android/app/src/main/res/values/strings.xml
+++ b/materialious/android/app/src/main/res/values/strings.xml
@@ -4,4 +4,5 @@
Materialious
us.materialio.app
us.materialio.app
+ Allows for audio to play in the background.
diff --git a/materialious/android/capacitor.settings.gradle b/materialious/android/capacitor.settings.gradle
index 1717e83a..83049c36 100644
--- a/materialious/android/capacitor.settings.gradle
+++ b/materialious/android/capacitor.settings.gradle
@@ -11,5 +11,8 @@ project(':capacitor-browser').projectDir = new File('../node_modules/@capacitor/
include ':capgo-inappbrowser'
project(':capgo-inappbrowser').projectDir = new File('../node_modules/@capgo/inappbrowser/android')
+include ':mediagrid-capacitor-native-audio'
+project(':mediagrid-capacitor-native-audio').projectDir = new File('../node_modules/@mediagrid/capacitor-native-audio/android')
+
include ':capacitor-nodejs'
project(':capacitor-nodejs').projectDir = new File('../node_modules/capacitor-nodejs/android')
diff --git a/materialious/package-lock.json b/materialious/package-lock.json
index fd975c6a..ceb30743 100644
--- a/materialious/package-lock.json
+++ b/materialious/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "materialious",
- "version": "1.5.0",
+ "version": "1.5.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "materialious",
- "version": "1.5.0",
+ "version": "1.5.4",
"dependencies": {
"@capacitor-community/electron": "^5.0.1",
"@capacitor/android": "6.1.2",
@@ -16,6 +16,7 @@
"@capacitor/core": "^6.1.2",
"@capgo/inappbrowser": "^6.6.8",
"@ffmpeg/ffmpeg": "^0.12.10",
+ "@mediagrid/capacitor-native-audio": "^1.0.0",
"beercss": "^3.7.7",
"capacitor-nodejs": "https://github.com/EdenwareApps/Capacitor-NodeJS/releases/download/v1.0.0-beta.7/capacitor6-nodejs.tgz",
"dashjs": "^4.7.4",
@@ -2725,6 +2726,14 @@
"resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz",
"integrity": "sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ=="
},
+ "node_modules/@mediagrid/capacitor-native-audio": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@mediagrid/capacitor-native-audio/-/capacitor-native-audio-1.0.0.tgz",
+ "integrity": "sha512-jYTKFqMnVxSwlRUm8pO1jGQgoF1dY00xFGJZXn1AUkSI7BLE+kEpVUYjsGn1CuMH5me9aEyOtiVaif5zF2Mwxw==",
+ "peerDependencies": {
+ "@capacitor/core": "^6.0.0"
+ }
+ },
"node_modules/@msgpack/msgpack": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz",
diff --git a/materialious/package.json b/materialious/package.json
index c03e93e3..01d7502d 100644
--- a/materialious/package.json
+++ b/materialious/package.json
@@ -52,6 +52,7 @@
"@capacitor/core": "^6.1.2",
"@capgo/inappbrowser": "^6.6.8",
"@ffmpeg/ffmpeg": "^0.12.10",
+ "@mediagrid/capacitor-native-audio": "^1.0.0",
"beercss": "^3.7.7",
"capacitor-nodejs": "https://github.com/EdenwareApps/Capacitor-NodeJS/releases/download/v1.0.0-beta.7/capacitor6-nodejs.tgz",
"dashjs": "^4.7.4",
@@ -71,4 +72,4 @@
"terser": "^5.33.0",
"vidstack": "^1.12.9"
}
-}
\ No newline at end of file
+}
diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte
index 2f189788..00f07035 100644
--- a/materialious/src/lib/Player.svelte
+++ b/materialious/src/lib/Player.svelte
@@ -3,6 +3,7 @@
import { page } from '$app/stores';
import { Capacitor } from '@capacitor/core';
+ import { AudioPlayer } from '@mediagrid/capacitor-native-audio';
import type { Page } from '@sveltejs/kit';
import { SponsorBlock, type Category, type Segment } from 'sponsorblock-api';
import { onDestroy, onMount } from 'svelte';
@@ -14,6 +15,7 @@
import type { VideoPlay } from './Api/model';
import {
getBestThumbnail,
+ proxyVideoUrl,
pullBitratePreference,
videoLength,
type PhasedDescription
@@ -337,6 +339,46 @@
}
await loadPlayerPos();
});
+
+ if (Capacitor.getPlatform() === 'android') {
+ const highestBitrateAudio = data.video.adaptiveFormats
+ .filter((format) => format.type.startsWith('audio/'))
+ .reduce((prev, current) => {
+ return parseInt(prev.bitrate) > parseInt(current.bitrate) ? prev : current;
+ });
+
+ const audioId = { audioId: data.video.videoId };
+
+ await AudioPlayer.create({
+ ...audioId,
+ audioSource: proxyVideoUrl(highestBitrateAudio.url),
+ friendlyTitle: data.video.title,
+ useForNotification: true,
+ loop: player.loop
+ });
+
+ await AudioPlayer.onAudioReady(audioId, async () => {
+ await AudioPlayer.initialize(audioId);
+ });
+
+ await AudioPlayer.onAppGainsFocus(audioId, async () => {
+ await AudioPlayer.pause(audioId);
+
+ const audioPlayerTime = await AudioPlayer.getCurrentTime(audioId);
+
+ player.currentTime = Number(audioPlayerTime.currentTime);
+ });
+
+ await AudioPlayer.onAppLosesFocus(audioId, async () => {
+ await player.pause();
+
+ await AudioPlayer.play(audioId);
+ await AudioPlayer.seek({
+ ...audioId,
+ timeInSeconds: Number(player.duration)
+ });
+ });
+ }
} else {
playerIsLive = true;
src = [
@@ -434,13 +476,14 @@
}
}
- onDestroy(() => {
+ onDestroy(async () => {
if (typeof silenceSkipperInterval !== 'undefined') {
clearInterval(silenceSkipperInterval);
}
savePlayerPos();
- player.pause();
+ await player.pause();
player.destroy();
+ await AudioPlayer.destroy({ audioId: data.video.videoId });
playerPosSet = false;
});