Last active
August 31, 2023 14:55
-
-
Save bananu7/2018055f77ad4dce3acb87b221630f69 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js'; | |
document.head.appendChild(script); | |
const url = '/filebrowser/api/raw/230827_095441/TRACK07.m4a?auth=...' | |
const audioElement = document.createElement('audio'); | |
audioElement.src = url; | |
document.body.appendChild(audioElement); | |
const audioCtx = new AudioContext(); | |
// Create a MediaElementAudioSourceNode | |
// Feed the HTMLMediaElement into it | |
const source = audioCtx.createMediaElementSource(audioElement); | |
// Create a gain node | |
const gainNode = audioCtx.createGain(); | |
// Create variables to store mouse pointer Y coordinate | |
// and HEIGHT of screen | |
let curY; | |
const HEIGHT = window.innerHeight; | |
// Get new mouse pointer coordinates when mouse is moved | |
// then set new gain value | |
document.onmousemove = updatePage; | |
function updatePage(e) { | |
curY = e.pageY; | |
gainNode.gain.value = curY / HEIGHT; | |
} | |
// Connect the AudioBufferSourceNode to the gainNode | |
// and the gainNode to the destination, so we can play the | |
// music and adjust the volume using the mouse cursor | |
source.connect(gainNode); | |
gainNode.connect(audioCtx.destination); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const loadScript = function(url) { | |
const script = document.createElement('script'); | |
script.type = 'text/javascript'; | |
script.src = url; | |
document.head.appendChild(script); | |
} | |
loadScript('https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js'); | |
loadScript('https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js') | |
loadScript('https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js') | |
const makeUrl = function(name) { | |
const path = '/filebrowser/api/raw/230827_095441/' | |
const auth = 'auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoyLCJsb2NhbGUiOiJlbiIsInZpZXdNb2RlIjoibW9zYWljIiwic2luZ2xlQ2xpY2siOmZhbHNlLCJwZXJtIjp7ImFkbWluIjpmYWxzZSwiZXhlY3V0ZSI6dHJ1ZSwiY3JlYXRlIjp0cnVlLCJyZW5hbWUiOnRydWUsIm1vZGlmeSI6dHJ1ZSwiZGVsZXRlIjp0cnVlLCJzaGFyZSI6dHJ1ZSwiZG93bmxvYWQiOnRydWV9LCJjb21tYW5kcyI6W10sImxvY2tQYXNzd29yZCI6ZmFsc2UsImhpZGVEb3RmaWxlcyI6ZmFsc2UsImRhdGVGb3JtYXQiOmZhbHNlfSwiaXNzIjoiRmlsZSBCcm93c2VyIiwiZXhwIjoxNjkzNDk0OTIxLCJpYXQiOjE2OTM0ODc3MjF9.AS9JdeDEVb889XB44cSW2A4j8Kke4KupUWWQ-DYx5z4'; | |
const inline = 'inline=true'; | |
return `${path}${name}?${auth}&${inline}`; | |
} | |
const urls = [ | |
'TRACK01.m4a', | |
'TRACK02.m4a', | |
'TRACK03.m4a', | |
'TRACK04.m4a', | |
'TRACK05.m4a', | |
'TRACK06.m4a', | |
'TRACK07.m4a', | |
'TRACK08.m4a', | |
].map(f => makeUrl(f)); | |
const makeAudio = function(url) { | |
const sound = new Howl({ | |
src: [url], | |
html5: true, | |
}); | |
return sound; | |
} | |
function PlayButton(props) { | |
return React.createElement('button', | |
{ | |
'onClick': () => props.sounds.forEach(s => s.play()), | |
}, | |
['Play'] | |
) | |
} | |
function StopButton(props) { | |
return React.createElement('button', | |
{ | |
'onClick': () => props.sounds.forEach(s => s.stop()), | |
}, | |
['Stop'] | |
) | |
} | |
function Seeker(props) { | |
return React.createElement('button', | |
{ | |
'onClick': () => props.sounds.forEach(s => s.seek(props.seconds)), | |
}, | |
[`Seek to ${props.seconds}`] | |
) | |
} | |
function Channel({ sound, name }) { | |
const parts = []; | |
const pos = String(sound.seek()); | |
parts.push(React.createElement('span', null, [name])); | |
parts.push(React.createElement('span', null, [pos])); | |
parts.push(React.createElement('input', { | |
type: 'checkbox', | |
onChange: (e) => { | |
console.log("triggering mute with", e.target.checked) | |
sound.mute(Boolean(e.target.checked)) | |
}, | |
})); | |
parts.push(React.createElement('input', { | |
type: 'range', | |
style: { | |
transform: 'rotateZ(270deg)', | |
}, | |
onChange: (e) => { sound.volume(e.target.value / 100) }, | |
})); | |
return React.createElement('div', { | |
style: { | |
border: '1px solid #ccc', | |
}, | |
padding: '5px', | |
}, parts); | |
} | |
function App(props) { | |
const [sounds, setSounds] = React.useState(null); | |
React.useEffect(() => { | |
console.log("rposp", props); | |
const soundObjects = props.urls.map(url => makeAudio(url)); | |
setSounds(soundObjects); | |
}, []); | |
if (!sounds) { | |
return "loading..."; | |
} | |
const items = []; | |
items.push(React.createElement(PlayButton, { sounds })) | |
items.push(React.createElement(StopButton, { sounds })) | |
items.push(React.createElement(Seeker, { sounds, seconds: 700 })) | |
const channels = sounds.map(sound => React.createElement(Channel, { sound, name: "channel name" })) | |
items.push(React.createElement('div', { | |
style: { | |
display: 'flex', | |
gap: '5px', | |
} | |
}, channels)); | |
return React.createElement('div', null, items); | |
} | |
const appDiv = document.createElement('div'); | |
appDiv.style = "background-color: #eee; width: 80vw; height: 80vw; position: absolute; left: 5vw; top: 5vh; padding: 50px; display: flex;"; | |
document.body.appendChild(appDiv); | |
ReactDOM.render(React.createElement(App, { urls }), appDiv); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment