Optimizing performance in mobile devices

Hi there I want to make a small android rhythm game but I have a performance problem. At the beginning of the scene the FPS is at 55 but after a while they drop to 30. It is important to mention that I not only use Phaser on my page, but also HTML elements, such as an audio tag, a video tag and several div tags. with flashy CSS colors, background and animations.

I need my game to be fluid, otherwise the user will be disappointed an surely will uninstall the app.

Please someone help me ?

Here is the HTML:

<html>
    <head>
        <title>Bear Harmony</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=640, height=360, initial-scale=1.0">
        
       	<link rel="icon" href="assets/images/icon.png">
       	
        <link rel="stylesheet" type="text/css" href="game/style.css">
        <link rel="stylesheet" type="text/css" href="libs/Animate/animate.css">
        <link rel="stylesheet" type="text/css" href="libs/Lyricer/lyricer.css">

        <script type="text/javascript" src="libs/Phaser/phaser.js"></script>
        <script type="text/javascript" src="libs/Phaser/plugins/SaveCPU.js"></script>
		<script type="text/javascript" src="libs/JSZip/jszip.js"></script>
        <script type="text/javascript" src="libs/Lyricer/lyricer.js"></script>
        <script type="text/javascript" src="game/constants.js"></script>
        <script type="text/javascript" src="game/game.js"></script>
        <script type="text/javascript" src="game/boot.js"></script>
        <script type="text/javascript" src="game/menu.js"></script>
        <script type="text/javascript" src="game/load.js"></script>
        <script type="text/javascript" src="game/play.js"></script>
        <script type="text/javascript" src="game/read.js"></script>
        <script type="text/javascript" src="game/make.js"></script>
        <script type="text/javascript" src="game/score.js"></script>
        <script type="text/javascript" src="game/loadZip.js"></script>
        
        <script>
        	function devlog(txt) {
        		var div = document.getElementById('dev-console');
        		div.innerHTML += txt+"<br>";
        		div.scrollTo({top:div.scrollHeight,left:0,behavior: "smooth",});
        	}
        	function deverr(txt) {
        		var div = document.getElementById('dev-console');
        		div.innerHTML += '<span style="color:red">'+txt+'</span><br>';
        		div.scrollTo({
        			top:div.scrollHeight,
        			left:0,
        			behavior: "smooth",
        		});
        	}        	
        	function devprint(txt) {
        		var div = document.getElementById('dev-output');
        		div.innerHTML = txt;
        	}
        	window.onerror = function(details, file, line) {
        		var arrs = file.split("/");
        		var filename = arrs[arrs.length-1];
        		var message = "<h3>"+details+"<br>Line "+line+" of "+filename+"<h3/>";
        		deverr(message);
        	}
        </script>
        
    </head>
    <body>
		
		<div id="rotation"></div>
		
		<div id="content" class="fullscreendiv">
			
			<!--logo-->
			<div id="logo"></div>
			
			<!--div for phaser game-->
			<div id="game"></div>
			
			<!--video and audio-->
			<video id="video" muted="muted" ></video>
			<audio id="audio"></audio>
			
			<!--hp bar, score and combo counter-->
			<meter id="hp-bar" value="50" min="0" max="100" low="20" high="100" optimum="50"></meter>
			<div id="score-counter" class="bhfont">0</div>
			<div id="combo-counter" class="tsfont blink"></div>
			
			<!--final score-->
			<div id="score" class="bhfont hidden">
				<h3 class="bhfont">Puntuación</h3>
				<div class="bhfont" id="scores"></div>
				<div id="scoreBkg"></div>
			</div>
			
			<!--main menu-->
			<div id="menu">
				<button ontouchend="showSelection()" style="position:absolute;top:10%;left:10%;width:40%;height:40%;" class="animate__animated animate__fast animate__backInRight">Seleccionar</button>
				<button ontouchend="showOpenZip()" style="position:absolute;top:10%;left:55%;width:35%;height:40%;" class="animate__animated animate__fast animate__delay-100ms animate__backInRight">Abrir ZIP</button>
				<button ontouchend="showEditor()" style="position:absolute;top:60%;left:10%;width:20%;height:30%;" class="animate__animated animate__fast animate__delay-200ms animate__backInLeft">Editor</button>
				<button ontouchend="showScores()" style="position:absolute;top:60%;left:35%;width:55%;height:30%;" class="animate__animated animate__fast animate__delay-500ms animate__backInLeft">Puntuaciones</button>
			</div>		
			<div id="select" class="bhfont hidden">
				<h3 class="bhfont">Seleccionar Canción</h3>
				<img id="songPreview">
				<div class="dsfont" id="metainfo"></div>
				<button ontouchend="prevSong()" style="position:absolute;top:25%;left:5%;width:10%;height:50%;">&lt;</button>
				<button ontouchend="nextSong()" style="position:absolute;top:25%;right:5%;width:10%;height:50%;">&gt;</button>
				<button ontouchend="toMenu();hidediv('select')" style="position:absolute; bottom:10%;left:5%; width:40%; padding-left:15px;padding-right:15px">Volver</button>
				<button ontouchend="startGame();hidediv('select')" style="position:absolute; bottom:10%;right:5%; width:40%; padding-left:15px;padding-right:15px">Jugar</button>
			</div>
			<div id="editor" class="bhfont hidden">
				<h3 class="bhfont">Editor</h3>
				<span class="dsfont">
					<p>El editor te permite crear archivos ZIP que puedes abrir en el juego.
					<p>El editor aún no está terminado por lo que podría resultar confuso el editar canciones.
				</span>
				<p>
				<button ontouchend="toMenu();hidediv('editor')" style="position:absolute; bottom:10%;left:5%; width:40%; padding-left:15px;padding-right:15px">Volver</button>
				<button ontouchend="openEditor()" style="position:absolute; bottom:10%;right:5%; width:40%; padding-left:15px;padding-right:15px">Ir al editor</button>
			</div>
			<div id="openzip" class="bhfont hidden">
				<h3 class="bhfont">Abrir ZIP</h3>
				<span class="dsfont">
					<p>La función Abrir ZIP te permite abrir un paquete creado en el editor.
					<p>Selecciona un archivo ZIP que hayas creado y luego pulsa JUGAR.
				</span>
				<p>
				<input id="zipfile" type="file" accept="application/zip">
				<button ontouchend="toMenu();hidediv('openzip')" style="position:absolute; bottom:10%;left:5%; width:40%; padding-left:15px;padding-right:15px">Volver</button>
				<button ontouchend="readZip();" style="position:absolute; bottom:10%;right:5%; width:40%; padding-left:15px;padding-right:15px">Jugar</button>
			</div>
			<div id="zipLoadingScreen" class="bhfont hidden">
				<div id="zipLoadingBkg"></div>
				<div style="text-align:left; position:absolute; bottom:10%;left:5%; width:80%; padding-left:15px;padding-right:15px; z-index:top;">Cargando archivo...</div>
			</div>
	
		</div>
		
		<div id="debug">
			<div id="dev-output"></div>
			<div id="dev-console"></div>
		</div>
		
		<div id="statsFrame">
			<div id="statsFps">N/A</div>
		</div>
		
    </body>
</html>

and here is the JS of the main game scene

var key1,key2,key3,key4;
var aud,vid;
var hpTween,scoreTween;
var currentNft = 0; 
var player = {
	score: 0,
	combo: 0,
	health: 50,
	perfect: 0,
	great: 0,
	good: 0,
	bad: 0,
	miss: 0
};
var internal = {
	loadingFromZip: false,
	gameOver: false,
};
// Play State
var Play = function () {
};
Play.prototype = {
	preload: function(){
	},
	create: function(){
		var ths = this;
		game.input.circle = new Phaser.Circle(0,0,72);
		this.batch = game.add.spriteBatch();
		function createKey(x,y,c) {
			key = game.add.sprite(x,y,'arrow_control',0);
			key.anchor.setTo(.5,.5);
			return key;
		}
		key1 = createKey(90,280,1);
		key2 = createKey(242,280,2);
		key3 = createKey(394,280,3);
		key4 = createKey(546,280,4);
		this.start();
	},
	update: function() {
		devprint("Debug: "+game.time.fps+"FPS S:"+game.time.suggestedFps+" hp:"+player.health);
	},
	// start game
	start: function(){
		this.setAudioVideo();
		this.addParticles();
		playSound('ready',false,1.0);
		playVoice('Miku_GameStart',14,0.3);
		playVoice('Trance_Ready',2,0.5);
	},
	// sync audio with video
	setAudioVideo: function() {
		aud = $('audio');
		vid = $('video');
		var localAudioUrl = 'data/'+folder+'/'+files.music;
		var localVideoUrl = 'data/'+folder+'/'+files.video;
		var localPosterUrl = 'data/'+folder+'/'+files.background;
		var zipAudioUrl = zipFile.music;
		var zipVideoUrl = zipFile.video;
		var zipPosterUrl = zipFile.background;
		if (internal.loadingFromZip) {
			aud.src = zipAudioUrl;
			vid.src = zipVideoUrl;
			vid.poster = zipPosterUrl;
			$('scoreBkg').style.backgroundImage = 'url("'+zipPosterUrl+'")';
		} else {
			aud.src = localAudioUrl;
			vid.src = localVideoUrl;
			vid.poster = localPosterUrl;
			$('scoreBkg').style.backgroundImage = 'url("'+localPosterUrl+'")';
		}
		aud.volume = volume;
		aud.addEventListener('pause', function (){
			vid.pause();
			vid.currentTime = aud.currentTime;
		});
		aud.addEventListener('play', function (){
			vid.play();
			vid.currentTime = aud.currentTime;
		});
		aud.addEventListener('seeked', function (){
			vid.currentTime = aud.currentTime;
		});
		game.time.events.add(2000, function (){
			aud.play();
			this.makeNotes();
		},this);
	},
	// make notes
	makeNotes: function(){
		currentNft = defaultnft;
		var ths = this;
		player = {score:0,combo:0,health:50,perfect:0,great:0,good:0,bad:0,miss:0};
		function addNote(code,nft){
			var dist = 360;
			const note = game.add.sprite({1:90,2:242,3:394,4:546}[code], -dist, 'notes', 'arrow_'+arrowcolor);
			note.angle = {1:0,2:90,3:270,4:180}[code];
			note.anchor.setTo(.5,.5);
			note.inputEnabled = true;
			note.code = code;
			note.sendToBack();
			note.input.priorityID = 100;
			note.events.onInputOver.add(function(){
				this.hitNote(note);
			},ths);
			note.checkWorldBounds = true;
			note.events.onEnterBounds.add(function(){
				note.events.onOutOfBounds.add(function (){
					this.missNote();
					note.kill();
				},ths);
			},ths);
			ths.batch.addChild(note);
			var t1 = game.add.tween(note);
			t1.to({y:280},nft,"Linear",true,0);
			t1.onComplete.add(function (){
				var t2 = game.add.tween(note);
				const nft2 = nft;
				t2.to({y:280+(280+dist)},nft2,"Linear",false,0);
				t2.start();
				// optimizar
				t2.onComplete.add(function (){
					t2.stop();
				});
				t1.stop();
			},ths);
		}
		for(var i=0;i<notes.length;i++){
			const note = notes[i];
			const num = i+1;
			function getNft(time){
				for(var i=0;i<nftchanges.length;i++){
					var s = nftchanges[i];
					var ns = nftchanges[i+1]||null;
					var t = s[0]*1000;
					var nt = (ns!=null)?ns[0]*1000:99999999999;
					if (time>=t) return s[1];
				}
			};
			game.time.events.add(((note.time*1000)-currentNft)+delay,function(){
				addNote(note.code,getNft(note.time*1000));
			});
		}
		for(var i=0;i<nftchanges.length;i++){
			const nft = nftchanges[i];
			game.time.events.add(((nft[0]*1000)-currentNft)+delay,function(){
				currentNft = nft[1];
			});
		}
		game.time.events.add(stars.first*1000, function (){
			this.getFirstStar();
		},this);
		game.time.events.add(stars.second*1000, function (){
			this.getSecondStar();
		},this);
		game.time.events.add(stars.third*1000, function (){
			this.getThirdStar();
		},this);
		var endtime = ($('audio').duration*1000)-2000;
		game.time.events.add(endtime,function(){
			this.finishSong();
			playSound('Perfect');
		},this);
		showdiv('hp-bar',true);
		showdiv('score-counter',true,'bhfont animate__animated animate__faster animate__delay-200ms animate__fadeInDown');
		this.updateHpBar();
		this.updateScore();
	},
	finishSong: function (){
		var s = game.add.sprite(640,0,'finish');
		var del = 360;
		var t1 = game.add.tween(s);
		t1.to({x:0},del,"Linear",true,0);
		var t2 = game.add.tween(s);
		t2.to({x:-640},del,"Linear",false,1000);
		t1.onComplete.add(function (){
			t2.start();
			vid.pause();
			vid.load();
			changeState('Score',600,0xFFFFFF);
		});
		hidediv('hp-bar');
		hidediv('combo-counter');
		hidediv('score-counter');
		internal.loadingFromZip = false;
	},
	hitNote: function(note) {
		var key = {1:key1,2:key2,3:key3,4:key4}[note.code];
		var angle = note.angle;
		if(!key.overlap(note))return;
		this.judgeNote(280-note.y,note,key);
		this.hitKey(key,note.x,angle);
		this.showCombo();
		note.kill();
	},
	judgeNote: function(diff,note,key){
		var judge = "perfect";
		var sumScore = 0;
		if (diff>11) judge = "great";
		if (diff>25) judge = "good";
		if (diff>40) judge = "bad";
		switch(judge){
			case "perfect":
				player.perfect++;
				sumScore = 1000;
				break;
			case "great":
				player.great++;
				sumScore = 500;
				break;
			case "good":
				player.good++;
				sumScore = 100;
				break;
			case "bad":
				player.bad++;
				sumScore = 10;
				player.combo = 0;
				break;
		}
		player.combo++;
		player.score += player.combo*sumScore;
		this.updateScore();
		this.healPlayer(3);
		const s = game.add.sprite(gameWidth/2,gameHeight/3,"judges",judge);
		s.anchor.setTo(.5,.5);
		s.scale.setTo(.55,.55);
		var del = currentNft/5;
		var t1 = game.add.tween(s.scale);
		t1.to({x:0.7,y:0.7},del/3,"Linear",true,0);
		t1.yoyo(true);
		t1.onComplete.add(function (){
			t1.stop();
		});
		var t2 = game.add.tween(s.scale);
		t2.to({x:1.5},del,"Linear",true,del);
		t2.onComplete.add(function (){
			t2.stop();
		});
		var t3 = game.add.tween(s);
		t3.to({alpha:0},del,"Linear",true,del);
		t3.onComplete.add(function (){
			s.kill
			t3.stop();
		});
	},
	updateScore: function (){
		$('score-counter').innerHTML = parse($('score-counter').innerHTML);
		scoreTween= game.add.tween($('score-counter'));
		scoreTween.to({innerHTML:player.score},120,"Linear",true,0);
		scoreTween.onUpdateCallback(function(){
			$('score-counter').innerHTML = parse($('score-counter').innerHTML).toFixed(0);
		},this);
		//animateCSS('score-counter','shineText');
	},
	showCombo: function (){
		if (player.combo<2) return;
		$('combo-counter').innerHTML = '<span style="font-size:24px">Combo </span><span class="kiaro" style="font-size:32px">x'+player.combo+'</span>';
		//animateCSS('combo-counter','shineText');
		if($('combo-counter').style.display=='none') $('combo-counter').style.display = 'block';
	},
	missNote: function(){
		const s = game.add.sprite(gameWidth/2,gameHeight/3,"judges","miss");
		s.anchor.setTo(.5,.5);
		s.scale.setTo(.55,.55);
		var del = currentNft/5;
		var t2 = game.add.tween(s.scale);
		t2.to({x:1.5},del,"Linear",true,del);
		var t3 = game.add.tween(s);
		t3.to({alpha:0},del,"Linear",true,del);
		t3.onComplete.add(function(){
			s.kill();
		});
		player.miss++;
		player.combo = 0;
		this.damagePlayer(10);
		$('combo-counter').style.display = 'none';
		if (player.health<=0) this.gameOver();
	},
	healPlayer: function(amount){
		if (player.health == 100) return;
		player.health += amount;
		this.updateHpBar();
	},
	damagePlayer: function(amount){
		if (player.health == 0) return;
		player.health -= amount;
		this.updateHpBar();
	},
	updateHpBar: function(){
		this.GameOver = Play.prototype.gameOver;
		if(player.health<0) {
			player.health = 0;
			this.GameOver();
		}
		if(player.health>100)player.health = 100;
		if(player.health<=20&&!this.healing)$('hp-bar').setAttribute('class','meter_low');
		else $('hp-bar').setAttribute('class','');
		hpTween = game.add.tween($('hp-bar'));
		hpTween.timeScale = 0.5;
		hpTween.to({value:player.health},120,"Elastic",true,0);
	},
	gameOver: function(){
		if (internal.gameOver) return;
		internal.gameOver = true;
		player.health = 0;
		playSound('GameOver');
		playVoice('Trance_GameOver',3,1);
		this.finishSong();
	},
	// key events
	hitKey: function(k,x,a) {
		k.frame = 1;
		k.scale.x = 1;
		k.scale.y = 1;
		var t1 = game.add.tween(k.scale);
		t1.to({x:1.2,y:1.2},50,"Linear",true,50);
		t1.yoyo(true);
		t1.onComplete.add(function (){
			k.frame = 0;
		});
		const note = game.add.sprite(x,280,'notes','arrow_'+arrowcolor);
		note.angle = a;
		note.anchor.setTo(.5,.5);
		var shine_time = currentNft/3;
		var t2 = game.add.tween(note.scale);
		t2.to({x:2.5,y:2.5},shine_time,"Linear",true,50);
		var t3 = game.add.tween(note);
		t3.to({alpha:0},shine_time,"Linear",true,50);
		t3.onComplete.add(note.kill);
		var comboVoiceVolume = aud.volume/2;
		switch (player.combo) {
			case 100:
				playSound('Trance_Combo_1',false,comboVoiceVolume);
				break;
			case 200:
				playSound('Trance_Combo_2',false,comboVoiceVolume);
				break;
			case 300:
				playSound('Trance_Combo_3',false,comboVoiceVolume);
				break;
			case 400:
				playSound('Trance_Combo_4',false,comboVoiceVolume);
				break;
			case 500:
				playSound('Trance_Combo_5',false,comboVoiceVolume);
				break;
			case 600:
				playSound('Trance_Combo_6',false,comboVoiceVolume);
				break;
			case 700:
				playSound('Trance_Combo_7',false,comboVoiceVolume);
				break;
			case 800:
				playSound('Trance_Combo_8',false,comboVoiceVolume);
				break;
			case 900:
				playSound('Trance_Combo_9',false,comboVoiceVolume);
				break;
			case 1000:
				playSound('Trance_Combo_10',false,comboVoiceVolume);
				break;
		}
	},
	// in game -
	getFirstStar: function () {
		this.createStar(1);
		playSound('magic1',false,0.3);
	},
	getSecondStar: function () {
		this.createStar(2);
		playSound('magic2',false,0.3);
	},
	getThirdStar: function () {
		this.createStar(3);
		playSound('magic3',false,0.3);
	},
	createStar: function (n) {
		const s = game.add.sprite(gameWidth/2,gameHeight/3,"star_128");
		s.anchor.setTo(.5,.5);
		s.scale.setTo(2,2);
		s.alpha = 0;
		var del = currentNft/5;
		var t1 = game.add.tween(s.scale);
		t1.to({x:1.2,y:1.2},del/3,"Linear",true,0);
		t1.yoyo(true);
		var t2 = game.add.tween(s);
		t2.to({alpha:1},del/3.7,"Linear",true,0);
		var t3 = game.add.tween(s);
		t3.to({alpha:0},del,"Linear",true,del);
		t3.onComplete.add(function (){
			s.kill
			t3.stop();
		});
		const s2 = game.add.sprite({1:(gameWidth/2)-32,2:gameWidth/2,3:(gameWidth/2)+32}[n],40,"star_32");
		s2.anchor.setTo(.5,.5);
		var fx = game.add.sprite(s2.x,s2.y,'particle_click');
		fx.anchor.setTo(.5,.5);
		fx.alpha = 1;
		fx.anim = fx.animations.add('anim',null,60,false,true);
		fx.anim.killOnComplete = true;
		fx.anim.play(60*2,false,true);
	},
	// particles
	addParticles: function () {
		back_emitter = game.add.emitter(game.world.centerX,-100,600);
		back_emitter.makeParticles('particle_a');
		back_emitter.maxParticleScale = 2.5;
		back_emitter.minParticleScale = 0.5;
		back_emitter.setYSpeed(20,100);
		back_emitter.setXSpeed(-200,200);
		back_emitter.gravity.y = 20;
		back_emitter.alpha = 0.1;
		back_emitter.width = game.world.width*1.3;
		back_emitter.minRotation = 0;
		back_emitter.maxRotation = 40;
		back_emitter.start(false,3000,20);
		click_emitter = game.add.emitter(0,0,100);
		click_emitter.makeParticles('particle_b');
		click_emitter.gravity = 0;
		click_emitter.maxParticleScale = 0.8;
		click_emitter.minParticleScale = 0.2;
		var v = 30;
		click_emitter.setYSpeed(v*-1,v);	
		click_emitter.setXSpeed(v*-1,v);
		game.input.addMoveCallback(function(pointer,x,y){
			click_emitter.x = pointer.x;
			click_emitter.y = pointer.y;
			if(pointer.duration>160)click_emitter.start(true,2000,null,1);
		},this);
	},
}