diff --git a/Dockerfile b/Dockerfile
index 1362e6153f2313012dc315390d278b25dde5288e..01cc4375a4d2c72844b0b78cfaf622fbc2dfd7a9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,4 +5,5 @@ RUN apt-get install -y libpq-dev  \
     && docker-php-ext-install pdo pdo_pgsql
 RUN a2enmod rewrite \
     && service apache2 restart
+RUN apt install -y ffmpeg
 #COPY src/web .htaccess /var/www/html/
\ No newline at end of file
diff --git a/src/sql/initial-data.sql b/src/sql/initial-data.sql
index cc38f674e4b99892ac371516c7a47c505bf423df..ff3b101946b889826a54311f7a94630c4f0a998a 100644
--- a/src/sql/initial-data.sql
+++ b/src/sql/initial-data.sql
@@ -29,6 +29,7 @@ create table if not exists music (
     album_id int not null,
     genre varchar(255),
     year int,
+    duration int not null,
     owner_account_id int,
     music_filename varchar(255),
     foreign key (album_id) references album(album_id),
diff --git a/src/web/music/music.php b/src/web/music/music.php
index 3e9ada1e5e143fae1016f059b718e5d38fe94846..b4888f9e1c8a2d512e4a29c2262813feee38537b 100644
--- a/src/web/music/music.php
+++ b/src/web/music/music.php
@@ -1,5 +1,12 @@
 <?php
 
+function getDuration($filename): int {
+    $dur = shell_exec("ffmpeg -i $filename 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//");
+    $dur = explode(':', $dur);
+
+    return (int) $dur[0] * 3600 + (int) $dur[1] * 60 + (int) $dur[2];
+}
+
 function addMusic(string $accountId, string $title, string $genre, string $year, string $albumId): int {
     $fileName = $_FILES['file']['name'];
     $fileName = str_replace(' ', '', $fileName);
@@ -30,12 +37,15 @@ function addMusic(string $accountId, string $title, string $genre, string $year,
     $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     curl_reset($curl);
 
+    $duration = getDuration($_FILES['file']['tmp_name']);
+
     if ($http_code == 200) {
-        $query = 'INSERT INTO music (title, album_id, genre, year, owner_account_id, music_filename) 
-                    VALUES(:title, :albumId, :genre, :year, :accountId, :fileName)';
+        $query = 'INSERT INTO music (title, album_id, genre, year, duration, owner_account_id, music_filename) 
+                    VALUES(:title, :albumId, :genre, :year, :duration, :accountId, :fileName)';
         $params = [
             'title' => $title,
             'year' => $year,
+            'duration' => $duration,
             'albumId' => $albumId,
             'genre' => $genre,
             'fileName' => $fileName,
diff --git a/src/web/presentation/music/info/albumInfo.php b/src/web/presentation/music/info/albumInfo.php
index 04325fc8fd2b3d7d06aefea30466d0416ffc0b11..d1078fb4c1a980ae05b9d1edade08dfd35ff253b 100644
--- a/src/web/presentation/music/info/albumInfo.php
+++ b/src/web/presentation/music/info/albumInfo.php
@@ -2,4 +2,72 @@
 
 if ($_SERVER['REQUEST_METHOD'] == 'GET') {
     require 'albumInfo.view.php';
+} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+    $data = json_decode(file_get_contents('php://input'), true);
+    $query = execSelect("SELECT owner_account_id, music_filename FROM music WHERE music_id = :id", ['id' => $data['id']]);
+    $accountId = $query[0]['owner_account_id'];
+    $fileName = $query[0]['music_filename'];
+
+    $params = http_build_query(array(
+        'owner' => $accountId, // account id,
+        'fileType' => 'music',
+        'fileName' => $fileName
+    ));
+
+    $curl = curl_init('object-storage:80/object?'.$params);
+    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+    $result = curl_exec($curl);
+
+    if (!curl_errno($curl) && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 200) {
+        $contentType = curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
+        $data = 'data:'.$contentType.';base64,'.base64_encode($result);
+        echo json_encode(['data' => $data]);
+    }
+    curl_close($curl);
+}
+
+function secondsToMinutes($duration): string {
+    $minutes = floor($duration / 60);
+    $seconds = $duration % 60;
+
+    if ($seconds < 10) {
+        $seconds = '0'.$seconds;
+    }
+
+    return $minutes.':'.$seconds;
+}
+
+function createListItem($class, $id, $title, $duration): void {
+    echo '<li class="'.$class.'">';
+    echo '    <p class="music-title" id="music-title">'.$title.'</p>';
+    echo '    <div class="music-sub-item">';
+    echo '        <p style="display: none" id="music-id">'.$id.'</p>';
+    echo '        <p class="music-duration">'.secondsToMinutes($duration).'</p>';
+    echo '    </div>';
+    echo '</li>';
+}
+
+function populateList($album_id): void {
+    $list = execSelect("SELECT music_id, title, duration FROM music WHERE album_id = :album_id", ['album_id' => $album_id]);
+
+    if (count($list) == 0) {
+        return;
+    }
+
+    if (count($list) == 1) {
+        createListItem('music-single-item', $list[0]['music_id'], $list[0]['title'], $list[0]['duration']);
+        return;
+    }
+
+    // top item
+    createListItem('music-item-top', $list[0]['music_id'], $list[0]['title'], $list[0]['duration']);
+
+    $midItems = array_slice($list, 1, count($list) - 2);
+
+    foreach ($midItems as $item) {
+        createListItem('music-item-mid', $item['music_id'], $item['title'], $item['duration']);
+    }
+
+    // bottom item
+    createListItem('music-item-bot', $list[count($list) - 1]['music_id'], $list[count($list) - 1]['title'], $list[count($list) - 1]['duration']);
 }
diff --git a/src/web/presentation/music/info/albumInfo.view.php b/src/web/presentation/music/info/albumInfo.view.php
index 621ac4c32d3fcfa7040a8e55daf2d5ba698ff60b..48bc322ef2706693b4e144e77675ee8d7046c7dc 100644
--- a/src/web/presentation/music/info/albumInfo.view.php
+++ b/src/web/presentation/music/info/albumInfo.view.php
@@ -1,22 +1,62 @@
+<?php
+
+require_once 'util/album-finder.php';
+require_once 'util/account-finder.php';
+
+$name = "";
+$artist = "";
+$year = "";
+
+function populateFields($id): void {
+    global $name, $artist, $year;
+
+    $result = execSelect("SELECT * FROM album WHERE album_id = :id", ['id' => $id]);
+
+    if (count($result) == 0) {
+        return;
+    }
+
+    $name = $result[0]['name'];
+    $artist = getAccountName($result[0]['owner_account_id']);
+    $year = $result[0]['year'];
+}
+
+?>
+
 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Artist - Album Title</title>
-    <link rel="stylesheet" href="presentation/music/info/css/albumInfo.css">
+    <link rel="stylesheet" href="/presentation/music/info/css/albumInfo.css">
     <link rel="preconnect" href="https://fonts.googleapis.com%22%3E/">
     <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
     <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
 </head>
 <body>
+<script src="/presentation/music/info/js/albumInfo.js" defer></script>
+<audio id="hidden-audio" src=""></audio>
 <div class="img-container">
-    <img src="presentation/music/info/img/defalbum.jpg" alt="Album">
+    <img src="<?php echo getAlbumImage() ?>" alt="Album">
 </div>
-<div id="album-info">
-    <p id="artist-title">Artist - Album Title</p>
-    <div class="more-info">
-        <p id="year">Year</p>
+    <div id="album-info">
+        <?php
+        $id = $_GET['id'] ?? null;
+        if (is_numeric($id)) {
+            populateFields($id);
+        }
+        ?>
+        <p id="artist-title"><?php echo $artist.' - '.$name ?></p>
+        <div class="more-info">
+            <p id="year"><?php echo $year ?></p>
+        </div>
+    </div>
+    <div id="music-list-d">
+        <ol id="music-list">
+            <?php
+            populateList($id);
+            ?>
+        </ol>
     </div>
-</div>
 </body>
 </html>
\ No newline at end of file
diff --git a/src/web/presentation/music/info/css/albumInfo.css b/src/web/presentation/music/info/css/albumInfo.css
index 912971c38408ed3e9c9484d162849549c8f9bb31..67c4c5eb6e1071efc68c461cd53b6e8df27ec2e4 100644
--- a/src/web/presentation/music/info/css/albumInfo.css
+++ b/src/web/presentation/music/info/css/albumInfo.css
@@ -26,4 +26,59 @@ html {
 #artist-title {
     font-size: 36px;
     margin-bottom: 0;
+}
+
+#music-list-d {
+    text-align: center;
+    width: 100%;
+}
+
+#music-list {
+    margin: auto;
+    width: 640px;
+    padding-left: 0;
+}
+
+#music-list li {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    padding: 12px;
+    border: 1px solid #e0e0e0;
+    cursor: pointer;
+}
+
+#hidden-audio {
+    display: none;
+}
+
+.music-item-top {
+    border-top-left-radius: 5px;
+    border-top-right-radius: 5px;
+}
+
+.music-item-mid {
+    border-top: none !important;
+}
+
+.music-item-bot {
+    border-top: none !important;
+    border-bottom-left-radius: 5px;
+    border-bottom-right-radius: 5px;
+}
+
+.music-single-item {
+    border-radius: 5px;
+}
+
+.music-sub-item {
+    display: flex;
+}
+
+.music-play {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    margin-right: 8px;
 }
\ No newline at end of file
diff --git a/src/web/presentation/music/info/js/albumInfo.js b/src/web/presentation/music/info/js/albumInfo.js
new file mode 100644
index 0000000000000000000000000000000000000000..05cd95a9777ff1a09c202b8d240fcccf71e0fe9c
--- /dev/null
+++ b/src/web/presentation/music/info/js/albumInfo.js
@@ -0,0 +1,29 @@
+const list = document.querySelector('#music-list').getElementsByTagName('li');
+
+for (let item of list) {
+    item.addEventListener('click', (e) => {
+        e.preventDefault();
+
+        let id = item.querySelector('#music-id').innerHTML;
+
+        let url = '/album';
+        let xhr = new XMLHttpRequest();
+
+        let data = {
+            id: id
+        }
+
+        xhr.open('POST', url, true);
+        xhr.setRequestHeader('Content-Type', 'application/json');
+        xhr.onreadystatechange = function() {
+            if (xhr.readyState === 4 && xhr.status === 200) {
+                let audio = JSON.parse(xhr.responseText);
+                let audioPlayer = document.querySelector('#hidden-audio');
+                audioPlayer.src = audio.data;
+                audioPlayer.play();
+            }
+        }
+
+        xhr.send(JSON.stringify(data));
+    });
+}
\ No newline at end of file