diff --git a/backend/src/Room.ts b/backend/src/Room.ts
index f22a8fa..ba5bf77 100644
--- a/backend/src/Room.ts
+++ b/backend/src/Room.ts
@@ -24,6 +24,7 @@ export default class Room {
 
     // For debugging purposes
     speedFactor = 1;
+    autoStart = false;
 
     constructor(name: number) {
         this.id = name;
@@ -59,6 +60,12 @@ export default class Room {
             this.setLeader(user);
         }
 
+        if (this.autoStart) {
+            this.seekTime = 2500000;
+            this.running = true;
+            this.start();
+        }
+
         this.sync();
     }
 
diff --git a/frontend/src/components/Centurion.tsx b/frontend/src/components/Centurion.tsx
index 0d9f301..061d628 100644
--- a/frontend/src/components/Centurion.tsx
+++ b/frontend/src/components/Centurion.tsx
@@ -16,12 +16,12 @@ const Centurion = () => {
 
     const feedContent = (
         
-            
             
                 
                 
                 
             
+            
         
     );
 
diff --git a/frontend/src/components/Player.ts b/frontend/src/components/Player.ts
deleted file mode 100644
index 59f82be..0000000
--- a/frontend/src/components/Player.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import {roomTime, useRoomRunningAndReadyChanged, useRoomTime, useTimelineSongFileChanged} from "../lib/Connection";
-import {useRef, useState} from "react";
-
-
-const Player = () => {
-    const roomRunning = useRoomRunningAndReadyChanged();
-    const _ = useRoomTime()
-    const timeline = useTimelineSongFileChanged();
-
-    const player = useRef(timeline ? new Audio(timeline.songFile) : null);
-
-    const [timesSeeked, setTimesSeeked] = useState(0);
-
-    // If our time synchronisation algorithm thing thinks the time is off by more
-    // than this value, we seek the running player to correct it.
-    const diffSecondsRequiredToSeekRunningPlayer = 0.20;
-
-    // Hard cap we are allowed to seek this player. Some browsers are slow or inaccurate
-    // and will always be off. To avoid endless skipping of the song this cap stops seeking the
-    // player.
-    const maxTimesSeekAllow = 20;
-
-    if (player.current && roomRunning?.running && roomRunning.readyToParticipate) {
-        let targetTime = roomTime() / 1000;
-        let diff = player.current.currentTime - targetTime;
-
-        console.log('PLAYER DIFF', 'Our time diff with the server: ', diff,
-            'Time required to seek (seconds): ', diffSecondsRequiredToSeekRunningPlayer);
-
-        if (Math.abs(diff) > diffSecondsRequiredToSeekRunningPlayer) {
-            if (roomRunning.speedFactor != 1 || timesSeeked < maxTimesSeekAllow) {
-                player.current.currentTime = targetTime;
-
-                player.current.playbackRate = Math.max(Math.min(4.0, roomRunning.speedFactor), 0.25);
-
-                setTimesSeeked(timesSeeked + 1);
-                console.log('SEEKED', 'The running player time was seeked, times seeked in total: ' + timesSeeked);
-            } else {
-                console.warn('The running player is off, but we\'ve changed the time ' +
-                    'too often, skipping synchronizing the player.');
-            }
-        }
-
-        if (player.current.paused) {
-            player.current.play().catch(e => {
-                console.error('Error playing', e);
-            })
-        }
-    } else {
-        if (player.current) {
-            player.current.pause();
-        }
-    }
-
-    return null;
-}
-
-export default Player;
\ No newline at end of file
diff --git a/frontend/src/components/Player.tsx b/frontend/src/components/Player.tsx
new file mode 100644
index 0000000..d77b15b
--- /dev/null
+++ b/frontend/src/components/Player.tsx
@@ -0,0 +1,110 @@
+import {roomTime, useRoomRunningAndReadyChanged, useRoomTime, useTimelineSongFileChanged} from "../lib/Connection";
+import React, {createRef, SyntheticEvent, useRef, useState} from "react";
+
+import '../css/player.sass'
+import {Room} from "../types/types";
+import {parse as parseQueryString} from "query-string";
+
+const Player = () => {
+    const room = useRoomRunningAndReadyChanged();
+    const _ = useRoomTime()
+    const timeline = useTimelineSongFileChanged();
+
+    let player = useRef(null)
+
+    const [timesSeeked, setTimesSeeked] = useState(0);
+    const [hadError, setHadError] = useState(false);
+
+    // If our time synchronisation algorithm thing thinks the time is off by more
+    // than this value, we seek the running player to correct it.
+    const diffSecondsRequiredToSeekRunningPlayer = 0.20;
+
+    // Hard cap we are allowed to seek this player. Some browsers are slow or inaccurate
+    // and will always be off. To avoid endless skipping of the song this cap stops seeking the
+    // player.
+    const maxTimesSeekAllow = 25;
+
+    const query = parseQueryString(window.location.search);
+    if (query.nosound) {
+        return null;
+    }
+
+    if (player.current && player.current.dataset.src != timeline!!.songFile) {
+        player.current.dataset.src = timeline!!.songFile;
+        player.current.src = timeline!!.songFile;
+    }
+
+    function handlePlayerOnPlay(e: SyntheticEvent) {
+        e.preventDefault();
+
+        // For when the user manually started the player for when autoplay is off.
+        setHadError(false);
+        if (shouldPlay()) {
+            startPlaying(true)
+        }
+    }
+
+    function shouldPlay() {
+        return player.current && timeline && room && room.running && room.readyToParticipate
+    }
+
+    function startPlaying(manual: boolean) {
+        if (!player.current) return;
+
+        if (player.current.paused && !hadError) {
+            player.current.play().then(() => {
+                setHadError(false);
+            }).catch(e => {
+                console.error('Error playing', e);
+                setHadError(true);
+            })
+        }
+
+        if (!hadError) {
+            setPlayerTime(room!!, manual);
+        }
+    }
+
+    function setPlayerTime(room: Room, manualAdjustment: boolean) {
+        if (!player.current) return;
+
+        let targetTime = roomTime() / 1000;
+        let diff = player.current.currentTime - targetTime;
+
+        console.log('PLAYER DIFF', diff,
+            'min req to seek: ', diffSecondsRequiredToSeekRunningPlayer);
+
+        if (player.current && Math.abs(diff) > diffSecondsRequiredToSeekRunningPlayer) {
+            if (room.speedFactor != 1 || manualAdjustment || timesSeeked < maxTimesSeekAllow) {
+                player.current.currentTime = targetTime;
+                player.current.playbackRate = Math.max(Math.min(4.0, room.speedFactor), 0.25);
+
+                if (!manualAdjustment) {
+                    setTimesSeeked(timesSeeked + 1);
+                }
+                console.log('PLAYER SEEKED', 'Player was seeked (total: ' + timesSeeked + ')');
+            } else {
+                console.warn('The running player is off, but we\'ve changed the time ' +
+                    'too often, skipping synchronizing the player.');
+            }
+        }
+    }
+
+    if (shouldPlay()) {
+        startPlaying(false)
+    } else {
+        if (player.current) {
+            player.current.pause();
+        }
+    }
+
+    function render() {
+        return (
+