mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 04:54:23 +00:00
commit to probably rewrite bpm detector
This commit is contained in:
0
frontend/src/client/audioProcessing.js
Normal file
0
frontend/src/client/audioProcessing.js
Normal file
@@ -9,22 +9,14 @@
|
|||||||
background: conic-gradient( blue, green, red, blue );
|
background: conic-gradient( blue, green, red, blue );
|
||||||
animation: gradientAnim 10s infinite linear;
|
animation: gradientAnim 10s infinite linear;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
transition: all 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beat {
|
.beat {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgba( 0, 0, 0, 0.2 );
|
background-color: rgba( 0, 0, 0, 0.2 );
|
||||||
animation: beatAnim 0.6s infinite linear;
|
display: none;
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes beatAnim {
|
|
||||||
0% {
|
|
||||||
background-color: rgba( 0, 0, 0, 0.2 );
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-color: rgba( 0, 0, 0, 0 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gradientAnim {
|
@keyframes gradientAnim {
|
||||||
|
|||||||
@@ -121,7 +121,12 @@ const getColourPalette = ( imageURL ) => {
|
|||||||
canvas.width = image.width ?? 500;
|
canvas.width = image.width ?? 500;
|
||||||
canvas.height = image.height ?? 500;
|
canvas.height = image.height ?? 500;
|
||||||
const ctx = canvas.getContext( '2d' );
|
const ctx = canvas.getContext( '2d' );
|
||||||
ctx.drawImage(image, 0, 0);
|
try {
|
||||||
|
ctx.drawImage( image, 0, 0 );
|
||||||
|
} catch ( err ) {
|
||||||
|
reject( err );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getImageData returns an array full of RGBA values
|
* getImageData returns an array full of RGBA values
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<title>Showcase - MusicPlayerV2</title>
|
<title>Showcase - MusicPlayerV2</title>
|
||||||
<link rel="stylesheet" href="/showcase.css">
|
<link rel="stylesheet" href="/showcase.css">
|
||||||
<link rel="stylesheet" href="/backgroundAnim.css">
|
<link rel="stylesheet" href="/backgroundAnim.css">
|
||||||
|
<script src="https://static.janishutz.com/libs/jquery/jquery.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
<div class="current-song">
|
<div class="current-song">
|
||||||
<span class="material-symbols-outlined fancy-view-song-art" v-if="!playingSong.hasCoverArt">music_note</span>
|
<span class="material-symbols-outlined fancy-view-song-art" v-if="!playingSong.hasCoverArt">music_note</span>
|
||||||
<img v-else :src="'/getSongCover?filename=' + playingSong.filename" class="fancy-view-song-art">
|
<img v-else :src="'/getSongCover?filename=' + playingSong.filename" class="fancy-view-song-art">
|
||||||
|
<progress max="1000" id="progress" :value="progressBar"></progress>
|
||||||
<h1>{{ playingSong.title }}</h1>
|
<h1>{{ playingSong.title }}</h1>
|
||||||
<p>{{ playingSong.artist }}</p>
|
<p>{{ playingSong.artist }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,7 +44,7 @@
|
|||||||
<div v-else>
|
<div v-else>
|
||||||
<h1>Loading...</h1>
|
<h1>Loading...</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="background">
|
<div class="background" id="background">
|
||||||
<div class="beat"></div>
|
<div class="beat"></div>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="canvas"></canvas>
|
<canvas id="canvas"></canvas>
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ createApp( {
|
|||||||
pos: 0,
|
pos: 0,
|
||||||
queuePos: 0,
|
queuePos: 0,
|
||||||
colourPalette: [],
|
colourPalette: [],
|
||||||
|
startTime: 0,
|
||||||
|
offsetTime: 0,
|
||||||
|
progressBar: 0,
|
||||||
|
timeTracker: null,
|
||||||
|
timeCorrector: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -25,9 +30,25 @@ createApp( {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
startTimeTracker () {
|
||||||
|
this.startTime = new Date().getTime();
|
||||||
|
this.timeTracker = setInterval( () => {
|
||||||
|
this.pos += 0.075;
|
||||||
|
this.progressBar = this.pos / this.playingSong.duration * 1000;
|
||||||
|
}, 75 );
|
||||||
|
|
||||||
|
this.timeCorrector = setInterval( () => {
|
||||||
|
this.pos = this.oldPos + ( new Date().getTime() - this.startTime ) / 1000;
|
||||||
|
this.progressBar = this.pos / this.playingSong.duration * 1000;
|
||||||
|
}, 5000 );
|
||||||
|
},
|
||||||
|
stopTimeTracker () {
|
||||||
|
clearInterval( this.timeTracker );
|
||||||
|
clearInterval( this.timeCorrector );
|
||||||
|
this.oldPos = this.pos;
|
||||||
|
},
|
||||||
connect() {
|
connect() {
|
||||||
let source = new EventSource( '/clientDisplayNotifier', { withCredentials: true } );
|
let source = new EventSource( '/clientDisplayNotifier', { withCredentials: true } );
|
||||||
|
|
||||||
source.onmessage = ( e ) => {
|
source.onmessage = ( e ) => {
|
||||||
let data;
|
let data;
|
||||||
try {
|
try {
|
||||||
@@ -40,15 +61,22 @@ createApp( {
|
|||||||
this.playingSong = data.data.playingSong ?? {};
|
this.playingSong = data.data.playingSong ?? {};
|
||||||
this.songs = data.data.songQueue ?? [];
|
this.songs = data.data.songQueue ?? [];
|
||||||
this.pos = data.data.pos ?? 0;
|
this.pos = data.data.pos ?? 0;
|
||||||
|
this.oldPos = data.data.pos ?? 0;
|
||||||
|
this.progressBar = this.pos / this.playingSong.duration * 1000;
|
||||||
this.queuePos = data.data.queuePos ?? 0;
|
this.queuePos = data.data.queuePos ?? 0;
|
||||||
|
if ( this.isPlaying ) this.startTimeTracker();
|
||||||
getColourPalette( '/getSongCover?filename=' + data.data.playingSong.filename ).then( palette => {
|
getColourPalette( '/getSongCover?filename=' + data.data.playingSong.filename ).then( palette => {
|
||||||
this.colourPalette = palette;
|
this.colourPalette = palette;
|
||||||
this.handleBackground();
|
this.handleBackground();
|
||||||
} ).catch( () => {
|
} ).catch( () => {
|
||||||
this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ]
|
this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ];
|
||||||
|
this.handleBackground();
|
||||||
} );
|
} );
|
||||||
} else if ( data.type === 'pos' ) {
|
} else if ( data.type === 'pos' ) {
|
||||||
this.pos = data.data;
|
this.pos = data.data;
|
||||||
|
this.oldPos = data.data;
|
||||||
|
this.startTime = new Date().getTime();
|
||||||
|
this.progressBar = data.data / this.playingSong.duration * 1000;
|
||||||
} else if ( data.type === 'isPlaying' ) {
|
} else if ( data.type === 'isPlaying' ) {
|
||||||
this.isPlaying = data.data;
|
this.isPlaying = data.data;
|
||||||
this.handleBackground();
|
this.handleBackground();
|
||||||
@@ -60,7 +88,8 @@ createApp( {
|
|||||||
this.colourPalette = palette;
|
this.colourPalette = palette;
|
||||||
this.handleBackground();
|
this.handleBackground();
|
||||||
} ).catch( () => {
|
} ).catch( () => {
|
||||||
this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ]
|
this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ];
|
||||||
|
this.handleBackground();
|
||||||
} );
|
} );
|
||||||
} else if ( data.type === 'queuePos' ) {
|
} else if ( data.type === 'queuePos' ) {
|
||||||
this.queuePos = data.data;
|
this.queuePos = data.data;
|
||||||
@@ -80,20 +109,39 @@ createApp( {
|
|||||||
}, false );
|
}, false );
|
||||||
},
|
},
|
||||||
handleBackground() {
|
handleBackground() {
|
||||||
|
// TODO: Consider using mic and realtime-bpm-analyzer
|
||||||
let colours = {};
|
let colours = {};
|
||||||
for ( let i = 0; i < 3; i++ ) {
|
if ( this.colourPalette[ 0 ] ) {
|
||||||
colours[ i ] = 'rgb(' + this.colourPalette[ i ].r + ',' + this.colourPalette[ i ].g + ',' + this.colourPalette[ i ].b + ')';
|
for ( let i = 0; i < 3; i++ ) {
|
||||||
}
|
colours[ i ] = 'rgb(' + this.colourPalette[ i ].r + ',' + this.colourPalette[ i ].g + ',' + this.colourPalette[ i ].b + ')';
|
||||||
$( '.background' ).css( 'background', `conic-gradient( ${ colours[ 0 ] }, ${ colours[ 1 ] }, ${ colours[ 2 ] }, ${ colours[ 0 ] } } )` );
|
}
|
||||||
if ( this.playingSong.bpm && this.isPlaying ) {
|
|
||||||
$( '.beat' ).show();
|
|
||||||
$( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm );
|
|
||||||
} else {
|
|
||||||
$( '.beat' ).hide();
|
|
||||||
}
|
}
|
||||||
|
$( '#background' ).css( 'background', `conic-gradient( ${ colours[ 0 ] }, ${ colours[ 1 ] }, ${ colours[ 2 ] }, ${ colours[ 0 ] } )` );
|
||||||
|
// if ( this.playingSong.bpm && this.isPlaying ) {
|
||||||
|
// $( '.beat' ).show();
|
||||||
|
// $( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm );
|
||||||
|
// $( '.beat' ).css( 'animation-delay', this.pos % ( 60 / this.playingSong.bpm * this.pos ) );
|
||||||
|
// } else {
|
||||||
|
// $( '.beat' ).hide();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.connect();
|
this.connect();
|
||||||
|
// Initialize Web Audio API components
|
||||||
|
const audioContext = new ( window.AudioContext || window.webkitAudioContext )();
|
||||||
|
// Start audio analysis
|
||||||
|
navigator.mediaDevices.getUserMedia( { audio: true } ).then( ( stream ) => {
|
||||||
|
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
isPlaying( value ) {
|
||||||
|
if ( value ) {
|
||||||
|
this.startTimeTracker();
|
||||||
|
} else {
|
||||||
|
this.stopTimeTracker();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} ).mount( '#app' );
|
} ).mount( '#app' );
|
||||||
|
|||||||
@@ -325,7 +325,9 @@ export default {
|
|||||||
},
|
},
|
||||||
setPos( pos ) {
|
setPos( pos ) {
|
||||||
let musicPlayer = document.getElementById( 'music-player' );
|
let musicPlayer = document.getElementById( 'music-player' );
|
||||||
|
this.playbackPos = pos;
|
||||||
musicPlayer.currentTime = pos;
|
musicPlayer.currentTime = pos;
|
||||||
|
this.sendUpdate( 'pos' );
|
||||||
},
|
},
|
||||||
showFancyView() {
|
showFancyView() {
|
||||||
this.$emit( 'update', { 'type': 'fancyView', 'status': true } );
|
this.$emit( 'update', { 'type': 'fancyView', 'status': true } );
|
||||||
|
|||||||
Reference in New Issue
Block a user