mirror of
https://github.com/stashapp/CommunityScripts.git
synced 2026-04-28 17:47:44 -05:00
Audio Player plugin (#546)
This commit is contained in:
39
plugins/AudioPlayer/AudioPlayer.css
Normal file
39
plugins/AudioPlayer/AudioPlayer.css
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Stash Audio Player */
|
||||
.VideoPlayer.audio .scrubber-wrapper,
|
||||
.VideoPlayer.audio .vjs-big-play-button,
|
||||
.VideoPlayer.audio .vjs-big-button-group,
|
||||
.VideoPlayer.audio .vjs-loading-spinner,
|
||||
.VideoPlayer.audio .vjs-skip-button {
|
||||
display: none !important;
|
||||
}
|
||||
.VideoPlayer.audio .vjs-control-bar {
|
||||
display: flex !important;
|
||||
opacity: 100 !important;
|
||||
}
|
||||
.VideoPlayer.audio .vjs-seek-button {
|
||||
display: block !important;
|
||||
}
|
||||
.VideoPlayer.audio .video-js {
|
||||
background-color: #202b33 !important;
|
||||
width: 100%;
|
||||
}
|
||||
.VideoPlayer.audio #VideoJsPlayer_html5_api {
|
||||
display: none !important;
|
||||
}
|
||||
.VideoPlayer.audio .video-wrapper {
|
||||
height: 7rem !important;
|
||||
overflow: visible;
|
||||
}
|
||||
.VideoPlayer.audio > .vjs-poster {
|
||||
height: 56.25vw !important;
|
||||
position: relative !important;
|
||||
}
|
||||
#audioToggle.enabled {
|
||||
color: #48aff0;
|
||||
}
|
||||
#audioToggle:hover {
|
||||
color: #fff;
|
||||
}
|
||||
#audioToggle {
|
||||
color: rgba(191,204,214,.5);
|
||||
}
|
||||
118
plugins/AudioPlayer/AudioPlayer.js
Normal file
118
plugins/AudioPlayer/AudioPlayer.js
Normal file
@@ -0,0 +1,118 @@
|
||||
// Stash Audio Player
|
||||
(async function () {
|
||||
"use strict"
|
||||
|
||||
const { waitForElement, PathElementListener, getConfiguration, callGQL, baseURL } = window.csLib
|
||||
|
||||
const defaultConfig = { audioExtensions: "mp3, m4a", useTag: false }
|
||||
const config = await getConfiguration("AudioPlayer", defaultConfig)
|
||||
const pluginConfig = {
|
||||
...defaultConfig,
|
||||
...config,
|
||||
}
|
||||
|
||||
function setAudioElement(bool) {
|
||||
const pl = document.querySelector(".VideoPlayer")
|
||||
var elm = document.getElementById("VideoJsPlayer_html5_api")
|
||||
const sourceElements = Array.from(
|
||||
document.querySelectorAll(
|
||||
"#VideoJsPlayer > div.vjs-control-bar > div.vjs-source-selector.vjs-menu-button.vjs-menu-button-popup.vjs-control.vjs-button > div > ul > li > span.vjs-menu-item-text"
|
||||
)
|
||||
)
|
||||
const hlsButton = sourceElements.find((el) => el.textContent.trim().toLowerCase() === "hls")
|
||||
if (bool) {
|
||||
pl.classList.add("audio")
|
||||
document.querySelector(".VideoPlayer .video-wrapper").before(document.querySelector(".vjs-poster"))
|
||||
if (hlsButton) {
|
||||
hlsButton.click()
|
||||
}
|
||||
} else {
|
||||
document.getElementById("VideoJsPlayer_html5_api").after(document.querySelector(".vjs-poster"))
|
||||
pl.classList.remove("audio")
|
||||
sourceElements[0].click()
|
||||
}
|
||||
}
|
||||
|
||||
function audiotoggle() {
|
||||
const elm = document.querySelector(".scene-toolbar-group")
|
||||
const btng = document.createElement("div")
|
||||
const btn = document.createElement("button")
|
||||
const pl = document.querySelector(".VideoPlayer")
|
||||
if (pl.classList.contains("audio")) {
|
||||
btn.classList.add("enabled")
|
||||
}
|
||||
btn.id = "audioToggle"
|
||||
btn.classList.add("minimal", "btn", "btn-secondary")
|
||||
//btn.innerHTML = "Audio Only";
|
||||
btn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="1rem" height="1rem" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2.25a.75.75 0 0 0-.75.75v11.26a4.25 4.25 0 1 0 1.486 2.888A1 1 0 0 0 12.75 17V7.75H18a2.75 2.75 0 1 0 0-5.5z"/></svg>`
|
||||
btn.onclick = function () {
|
||||
const pl = document.querySelector(".VideoPlayer")
|
||||
const bt = document.getElementById("audioToggle")
|
||||
if (pl.classList.contains("audio")) {
|
||||
setAudioElement(false)
|
||||
bt.classList.remove("enabled")
|
||||
} else {
|
||||
setAudioElement(true)
|
||||
bt.classList.add("enabled")
|
||||
}
|
||||
}
|
||||
btng.classList.add("btn-group")
|
||||
btng.appendChild(btn)
|
||||
elm.appendChild(btng)
|
||||
}
|
||||
|
||||
async function getScene() {
|
||||
const currentPath = window.location.pathname
|
||||
const idRegExp = /\/scenes\/(\d+).*/
|
||||
const id = idRegExp.exec(currentPath)[1]
|
||||
const query = `query FindScene($id: ID!, $checksum: String) {findScene(id: $id, checksum: $checksum) { id\n files { id\n path\n __typename }\n tags { id\n name\n __typename }\n __typename}}`
|
||||
const variables = { id }
|
||||
const response = await callGQL({ query, variables })
|
||||
return response
|
||||
}
|
||||
|
||||
function findAudioTag(sceneInfo) {
|
||||
const tags = sceneInfo["findScene"]["tags"]
|
||||
const audioTag = tags.find((tag) => tag.name === "Audio")
|
||||
if (audioTag) {
|
||||
setAudioElement(true)
|
||||
}
|
||||
// waitForElement(".tag-item", function (){
|
||||
// const links = document.querySelectorAll('.tag-item a');
|
||||
// if (links) {
|
||||
// links.forEach(link => {
|
||||
// const divText = link.querySelector('div').textContent.trim();
|
||||
// if (divText === "Audio") {
|
||||
// setAudioElement(true);
|
||||
// }
|
||||
// });
|
||||
// }})
|
||||
}
|
||||
|
||||
function findAudioExtension(sceneInfo) {
|
||||
const filesExt = sceneInfo["findScene"]["files"].map((file) => {
|
||||
const fileNameArray = file.path.split(".")
|
||||
return fileNameArray[fileNameArray.length - 1]
|
||||
})
|
||||
const extToSearch = pluginConfig["audioExtensions"].split(",").map((ext) => ext.trim())
|
||||
const audioFiles = filesExt.find((ext) => extToSearch.includes(ext))
|
||||
if (audioFiles) {
|
||||
setAudioElement(true)
|
||||
}
|
||||
}
|
||||
|
||||
PathElementListener(
|
||||
baseURL + "scenes/",
|
||||
"#VideoJsPlayer > div.vjs-control-bar > div.vjs-source-selector.vjs-menu-button.vjs-menu-button-popup.vjs-control.vjs-button > div > ul > li > span.vjs-menu-item-text",
|
||||
async function () {
|
||||
const sceneInfo = await getScene()
|
||||
const useTag = pluginConfig["useTag"]
|
||||
if (useTag) {
|
||||
findAudioTag(sceneInfo)
|
||||
} else {
|
||||
findAudioExtension(sceneInfo)
|
||||
}
|
||||
waitForElement(".scene-toolbar-group", audiotoggle)
|
||||
}
|
||||
)
|
||||
})()
|
||||
20
plugins/AudioPlayer/AudioPlayer.yml
Normal file
20
plugins/AudioPlayer/AudioPlayer.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
name: AudioPlayer
|
||||
description: Add an audio-only toggle button and support for audio files in the Stash player through hls transcoder.
|
||||
version: 0.3
|
||||
ui:
|
||||
requires:
|
||||
- CommunityScriptsUILibrary
|
||||
javascript:
|
||||
- AudioPlayer.js
|
||||
css:
|
||||
- AudioPlayer.css
|
||||
|
||||
settings:
|
||||
audioExtensions:
|
||||
displayName: Audio Extensions
|
||||
description: "Extensions to mach as audio files. Default: mp3, m4a"
|
||||
type: STRING
|
||||
useTag:
|
||||
displayName: Use Tag
|
||||
description: Use "Audio" tag instead of extensions.
|
||||
type: BOOLEAN
|
||||
30
plugins/AudioPlayerLite/AudioPlayerLite.css
Normal file
30
plugins/AudioPlayerLite/AudioPlayerLite.css
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Stash Audio Player Lite */
|
||||
.VideoPlayer.audio .scrubber-wrapper,
|
||||
.VideoPlayer.audio .vjs-big-play-button,
|
||||
.VideoPlayer.audio .vjs-big-button-group,
|
||||
.VideoPlayer.audio .vjs-loading-spinner,
|
||||
.VideoPlayer.audio .vjs-skip-button {
|
||||
display: none !important;
|
||||
}
|
||||
.VideoPlayer.audio .vjs-control-bar {
|
||||
display: flex !important;
|
||||
opacity: 100 !important;
|
||||
}
|
||||
.VideoPlayer.audio .vjs-seek-button {
|
||||
display: block !important;
|
||||
}
|
||||
.VideoPlayer.audio .video-js {
|
||||
background-color: #202b33 !important;
|
||||
width: 100%;
|
||||
}
|
||||
.VideoPlayer.audio #VideoJsPlayer_html5_api {
|
||||
display: none !important;
|
||||
}
|
||||
.VideoPlayer.audio .video-wrapper {
|
||||
height: 7rem !important;
|
||||
overflow: visible;
|
||||
}
|
||||
.VideoPlayer.audio > .vjs-poster {
|
||||
height: 56.25vw !important;
|
||||
position: relative !important;
|
||||
}
|
||||
35
plugins/AudioPlayerLite/AudioPlayerLite.js
Normal file
35
plugins/AudioPlayerLite/AudioPlayerLite.js
Normal file
@@ -0,0 +1,35 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
const PluginApi = window.PluginApi;
|
||||
const React = PluginApi.React;
|
||||
|
||||
function setStyle() {
|
||||
if(!document.querySelector(".VideoPlayer .video-wrapper") || !document.querySelector(".vjs-poster")) {
|
||||
window.setTimeout(setStyle, 100)
|
||||
} else {
|
||||
document.querySelector(".VideoPlayer .video-wrapper").before(document.querySelector(".vjs-poster"))
|
||||
document.querySelector(".VideoPlayer").classList.add("audio")
|
||||
}
|
||||
}
|
||||
|
||||
PluginApi.Event.addEventListener("stash:location", async (e) => {
|
||||
const path = e.detail.data.location.pathname;
|
||||
const idRegExp = /.*\/scenes\/(\d+)/;
|
||||
if (idRegExp.test(path)) {
|
||||
await PluginApi.utils.loadComponents([
|
||||
PluginApi.loadableComponents.ScenePlayer
|
||||
]);
|
||||
PluginApi.patch.instead("ScenePlayer", function (props, _, originalComponent) {
|
||||
const file = props.scene.files[0];
|
||||
let scene = props.scene;
|
||||
if (file.video_codec === "") {
|
||||
scene = { ...scene,
|
||||
sceneStreams: props.scene.sceneStreams.filter((ss) => ss.label.toUpperCase() === 'HSL')
|
||||
};
|
||||
poster()
|
||||
}
|
||||
return originalComponent({ ...props, scene });
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
8
plugins/AudioPlayerLite/AudioPlayerLite.yml
Normal file
8
plugins/AudioPlayerLite/AudioPlayerLite.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
name: AudioPlayerLite
|
||||
description: This plugin identifies files with no video codec and plays them as audio.
|
||||
version: 0.1
|
||||
ui:
|
||||
javascript:
|
||||
- AudioPlayerLite.js
|
||||
css:
|
||||
- AudioPlayerLite.css
|
||||
Reference in New Issue
Block a user