From 04c4efb9a212e1f449a1688e1c4d18058040e649 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 02:06:01 +1200 Subject: [PATCH 1/7] Bump version --- materialious/android/app/build.gradle | 4 ++-- materialious/electron/package.json | 2 +- materialious/package.json | 2 +- update_versions.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/materialious/android/app/build.gradle b/materialious/android/app/build.gradle index 14751195..195611f4 100644 --- a/materialious/android/app/build.gradle +++ b/materialious/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "us.materialio.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 44 - versionName "1.5.3" + versionCode 45 + versionName "1.5.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/materialious/electron/package.json b/materialious/electron/package.json index bbb21784..b419410c 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -1,6 +1,6 @@ { "name": "Materialious", - "version": "1.5.3", + "version": "1.5.4", "description": "Modern material design for Invidious.", "author": { "name": "Ward Pearce", diff --git a/materialious/package.json b/materialious/package.json index 8cf5c93e..c03e93e3 100644 --- a/materialious/package.json +++ b/materialious/package.json @@ -1,6 +1,6 @@ { "name": "materialious", - "version": "1.5.3", + "version": "1.5.4", "private": true, "scripts": { "dev": "vite dev", diff --git a/update_versions.py b/update_versions.py index 093cc790..d802a161 100644 --- a/update_versions.py +++ b/update_versions.py @@ -5,7 +5,7 @@ import json import os import re -LATEST_VERSION = "1.5.3" +LATEST_VERSION = "1.5.4" WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious") ROOT_PACKAGE = os.path.join(WORKING_DIR, "package.json") From 0f3803c03896c67f560ecd810542ce90ec25713d Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 03:29:41 +1200 Subject: [PATCH 2/7] Steps towards using local video fallback on android --- materialious/src/lib/Api/index.ts | 5 +- materialious/src/lib/Player.svelte | 2 +- materialious/src/lib/Settings.svelte | 53 ++++++++++++------- materialious/src/lib/i18n/locales/en.json | 3 +- .../src/lib/patches/androidRequests.ts | 2 +- materialious/src/lib/store.ts | 1 + 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/materialious/src/lib/Api/index.ts b/materialious/src/lib/Api/index.ts index 32e8fb7f..d0bbef1b 100644 --- a/materialious/src/lib/Api/index.ts +++ b/materialious/src/lib/Api/index.ts @@ -7,6 +7,7 @@ import { deArrowThumbnailInstanceStore, instanceStore, interfaceRegionStore, + playerYouTubeJsAlways, playerYouTubeJsFallback, returnYTDislikesInstanceStore, synciousInstanceStore @@ -72,7 +73,9 @@ export async function getPopular(fetchOptions?: RequestInit): Promise { export async function getVideo(videoId: string, local: boolean = false, fetchOptions?: RequestInit): Promise { const resp = await fetch(setRegion(buildPath(`videos/${videoId}?local=${local}`)), fetchOptions); - if (!resp.ok && Capacitor.isNativePlatform() && get(playerYouTubeJsFallback)) { + if ( + (get(playerYouTubeJsAlways) && Capacitor.isNativePlatform()) || + (!resp.ok && get(playerYouTubeJsFallback) && Capacitor.isNativePlatform())) { return await patchYoutubeJs(videoId); } else { await fetchErrorHandle(resp); diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index 481f7c5b..2f189788 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -326,7 +326,7 @@ src = [{ src: data.video.dashUrl, type: 'application/dash+xml' }]; if (!data.video.fallbackPatch) { - if (Capacitor.getPlatform() !== 'electron' || proxyVideos) { + if (!Capacitor.isNativePlatform() || proxyVideos) { (src[0] as { src: string }).src += '?local=true'; } } diff --git a/materialious/src/lib/Settings.svelte b/materialious/src/lib/Settings.svelte index 18f7cfee..88110d49 100644 --- a/materialious/src/lib/Settings.svelte +++ b/materialious/src/lib/Settings.svelte @@ -29,6 +29,7 @@ playerProxyVideosStore, playerSavePlaybackPositionStore, playerTheatreModeByDefaultStore, + playerYouTubeJsAlways, playerYouTubeJsFallback, returnYTDislikesInstanceStore, returnYtDislikesStore, @@ -258,6 +259,40 @@
{$_('layout.player.title')}
+ {#if Capacitor.isNativePlatform()} +
+ +
+ +
+ +
+ {/if} +
- - {#if Capacitor.isNativePlatform()} -
- -
- {/if}
diff --git a/materialious/src/lib/i18n/locales/en.json b/materialious/src/lib/i18n/locales/en.json index ffc8e00d..79285e02 100644 --- a/materialious/src/lib/i18n/locales/en.json +++ b/materialious/src/lib/i18n/locales/en.json @@ -125,7 +125,8 @@ "backgroundPlay": "Play audio in background", "dash": "Dash", "silenceSkipper": "Silence skipper (Experimental)", - "youtubeJsFallback": "Local video processing fallback" + "youtubeJsFallback": "Local video processing fallback", + "youtubeJsAlways": "Always use local video processing" }, "bookmarklet": "Bookmarklet", "instanceUrl": "Instance URL", diff --git a/materialious/src/lib/patches/androidRequests.ts b/materialious/src/lib/patches/androidRequests.ts index 155a240e..30e18f44 100644 --- a/materialious/src/lib/patches/androidRequests.ts +++ b/materialious/src/lib/patches/androidRequests.ts @@ -14,7 +14,7 @@ if (Capacitor.getPlatform() === 'android') { typeof requestInput === 'string' ? requestInput : requestInput.toString(); // Check if the URL is already proxied, to avoid double proxying - if (!requestUrl.startsWith(corsAnywhereProxyUrl) && !requestUrl.startsWith('/')) { + if (!requestUrl.startsWith(corsAnywhereProxyUrl) && !requestUrl.startsWith('/') && !requestUrl.startsWith('blob:') && !requestUrl.startsWith('/')) { requestInput = corsAnywhereProxyUrl + requestUrl; } diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index 116481c9..fee4fb3c 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -39,6 +39,7 @@ export const playerTheatreModeByDefaultStore = persisted('theatreModeByDefault', export const playerAutoplayNextByDefaultStore = persisted('autoplayNextByDefault', false); export const playerMiniPlayerStore = persisted('miniPlayer', true); export const playerYouTubeJsFallback = persisted('youTubeJsFallback', true); +export const playerYouTubeJsAlways = persisted('youTubeJsAlways', false); export const returnYtDislikesStore = persisted('returnYtDislikes', false); export const returnYTDislikesInstanceStore: Writable = persisted( From 3b03852a77cabc633d3393d18ced65e0f7734fdc Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 03:47:25 +1200 Subject: [PATCH 3/7] Add background audio logic for Android --- .../android/app/capacitor.build.gradle | 1 + .../android/app/src/main/AndroidManifest.xml | 14 ++++++ .../app/src/main/res/values/strings.xml | 1 + .../android/capacitor.settings.gradle | 3 ++ materialious/package-lock.json | 13 ++++- materialious/package.json | 3 +- materialious/src/lib/Player.svelte | 47 ++++++++++++++++++- 7 files changed, 77 insertions(+), 5 deletions(-) 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; }); From b25d429873d55aa00e3f864f2f536e29289d4692 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 03:58:27 +1200 Subject: [PATCH 4/7] initialize --- materialious/src/lib/Player.svelte | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index 00f07035..e0d6bf5f 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -357,10 +357,6 @@ loop: player.loop }); - await AudioPlayer.onAudioReady(audioId, async () => { - await AudioPlayer.initialize(audioId); - }); - await AudioPlayer.onAppGainsFocus(audioId, async () => { await AudioPlayer.pause(audioId); @@ -378,6 +374,8 @@ timeInSeconds: Number(player.duration) }); }); + + await AudioPlayer.initialize(audioId); } } else { playerIsLive = true; From 2dd9f736cab3921d46ae3ac76c2755504ea9b309 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 04:00:34 +1200 Subject: [PATCH 5/7] dont use await --- materialious/src/lib/Player.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index e0d6bf5f..90149b9f 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -357,7 +357,7 @@ loop: player.loop }); - await AudioPlayer.onAppGainsFocus(audioId, async () => { + AudioPlayer.onAppGainsFocus(audioId, async () => { await AudioPlayer.pause(audioId); const audioPlayerTime = await AudioPlayer.getCurrentTime(audioId); @@ -365,7 +365,7 @@ player.currentTime = Number(audioPlayerTime.currentTime); }); - await AudioPlayer.onAppLosesFocus(audioId, async () => { + AudioPlayer.onAppLosesFocus(audioId, async () => { await player.pause(); await AudioPlayer.play(audioId); From fe217f4d729dcfa0236f1a16190b7baf2ce45a66 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 04:13:18 +1200 Subject: [PATCH 6/7] Fixes to background play --- materialious/src/lib/Player.svelte | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index 90149b9f..610479ae 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -354,7 +354,8 @@ audioSource: proxyVideoUrl(highestBitrateAudio.url), friendlyTitle: data.video.title, useForNotification: true, - loop: player.loop + loop: player.loop, + isBackgroundMusic: false }); AudioPlayer.onAppGainsFocus(audioId, async () => { @@ -362,16 +363,15 @@ const audioPlayerTime = await AudioPlayer.getCurrentTime(audioId); - player.currentTime = Number(audioPlayerTime.currentTime); + player.currentTime = Math.round(audioPlayerTime.currentTime); + await player.play(); }); AudioPlayer.onAppLosesFocus(audioId, async () => { - await player.pause(); - await AudioPlayer.play(audioId); await AudioPlayer.seek({ ...audioId, - timeInSeconds: Number(player.duration) + timeInSeconds: Math.round(player.currentTime) }); }); @@ -475,13 +475,15 @@ } onDestroy(async () => { + if (Capacitor.getPlatform() === 'android') { + await AudioPlayer.destroy({ audioId: data.video.videoId }); + } if (typeof silenceSkipperInterval !== 'undefined') { clearInterval(silenceSkipperInterval); } savePlayerPos(); await player.pause(); player.destroy(); - await AudioPlayer.destroy({ audioId: data.video.videoId }); playerPosSet = false; }); From fc2ec26edaea26aed89f123551fee0365e839311 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 21 Sep 2024 04:26:56 +1200 Subject: [PATCH 7/7] Add option to disable audio in bg --- materialious/src/lib/Player.svelte | 15 +++-- materialious/src/lib/Settings.svelte | 87 +++++++++++++++++----------- materialious/src/lib/store.ts | 1 + 3 files changed, 63 insertions(+), 40 deletions(-) diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index 610479ae..416c0f5a 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -25,6 +25,7 @@ instanceStore, miniPlayerSrcStore, playerAlwaysLoopStore, + playerAndroidBgPlayer, playerAutoPlayStore, playerProxyVideosStore, playerSavePlaybackPositionStore, @@ -340,7 +341,7 @@ await loadPlayerPos(); }); - if (Capacitor.getPlatform() === 'android') { + if (Capacitor.getPlatform() === 'android' && get(playerAndroidBgPlayer)) { const highestBitrateAudio = data.video.adaptiveFormats .filter((format) => format.type.startsWith('audio/')) .reduce((prev, current) => { @@ -368,11 +369,13 @@ }); AudioPlayer.onAppLosesFocus(audioId, async () => { - await AudioPlayer.play(audioId); - await AudioPlayer.seek({ - ...audioId, - timeInSeconds: Math.round(player.currentTime) - }); + if (!player.paused) { + await AudioPlayer.play(audioId); + await AudioPlayer.seek({ + ...audioId, + timeInSeconds: Math.round(player.currentTime) + }); + } }); await AudioPlayer.initialize(audioId); diff --git a/materialious/src/lib/Settings.svelte b/materialious/src/lib/Settings.svelte index 88110d49..07995851 100644 --- a/materialious/src/lib/Settings.svelte +++ b/materialious/src/lib/Settings.svelte @@ -22,6 +22,7 @@ interfaceRegionStore, interfaceSearchSuggestionsStore, playerAlwaysLoopStore, + playerAndroidBgPlayer, playerAutoPlayStore, playerAutoplayNextByDefaultStore, playerListenByDefaultStore, @@ -259,40 +260,6 @@
{$_('layout.player.title')}
- {#if Capacitor.isNativePlatform()} -
- -
- -
- -
- {/if} -
+ {#if Capacitor.getPlatform() === 'android'} +
+ +
+ {/if} + {#if Capacitor.isNativePlatform()}
+ + {#if Capacitor.isNativePlatform()} +
+ +
+ +
+ +
+ {/if}
diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index fee4fb3c..7aa226a9 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -40,6 +40,7 @@ export const playerAutoplayNextByDefaultStore = persisted('autoplayNextByDefault export const playerMiniPlayerStore = persisted('miniPlayer', true); export const playerYouTubeJsFallback = persisted('youTubeJsFallback', true); export const playerYouTubeJsAlways = persisted('youTubeJsAlways', false); +export const playerAndroidBgPlayer = persisted('androidBgPlayer', true); export const returnYtDislikesStore = persisted('returnYtDislikes', false); export const returnYTDislikesInstanceStore: Writable = persisted(