Tạo ứng dụng hát karaoke bằng HTML5-Audio

Trong cuộc sống, đôi khi mình hay tìm vài trò vui vui để làm với công việc của mình, nó giúp mình giảm stress và cảm thấy công việc có ý nghĩa hơn. Mình thì cũng có chút sở thích về hát hò, mà công việc chính lại là coder, vậy nên hôm nay mình sẽ dùng code để viết ra một ứng dụng hát karaoke bằng HTML5-Audio kết hợp với Javascript và CSS. Nếu bạn quan tâm thì hãy xem bài viết này và cho mình thêm góp ý nhé!

1. Ý tưởng và thực hành

Sau khi ngồi nghe vài bài hát trên Zing-MP3, mình để ý ở trình player của nó có một chức năng là highlight các đoạn lời bài hát theo đúng giai điệu. Tính mình cũng tò mò, nên quyết định vận dụng mấy cái kiến thức về WEB của mình để làm ra một cái ứng dụng tương tự.

1.1 Chuẩn bị

# Đầu tiên, mình cần một thứ để có thể load được bài hát và control được nó (play, pause, seek). Thì trên HTML5 có một thành phần là audio hỗ trợ tất cả các yêu cầu mà mình mong muốn nên mình sẽ dùng thằng này.

<audio></audio>

# Tiếp theo, mình cần một tập các đoạn lời trong bài hát. Cái này thì mình phải tự tạo bằng tay. Mình tạo ra một mảng gồm các mảng con, mỗi mảng con chứa thông tin của một đoạn lời bài hát gồm [lời bài hát, thời gian bắt đầu, thời gian kết thúc]. Tạo kiểu mảng như vậy thì sẽ dễ xử lý hơn.

var lyrics = [
  ['Đêm nghe hạt mưa rơi', 23.516146, 25.81885],
  ['Lòng chợt nhớ em vô cùng', 26, 30.344052],
  // ...
];

1.2 Xử lý logic

# Khi các bạn play hoặc seek đoạn nhạc đến các khoảng thời gian khác nhau, thì cần tính toán xem sẽ hiển thị đoạn lời nào ra. Mình viết một hàm tạm đặt tên là findLyricIndex để làm nhiệm vụ này.

var audio = document.getElementById('audio');

var lyrics = [
  ['Đêm nghe hạt mưa rơi', 23.516146, 25.81885],
  ['Lòng chợt nhớ em vô cùng', 26, 30.344052],
  // ...
];

// ...

var findLyricIndex = function () {
  if (audio.currentTime === 0) {
    return 0;
  }
  for (var i = 0; i < lyrics.length; i++) {
    if (audio.currentTime >= lyrics[i][1] && audio.currentTime <= lyrics[i][2]) {
      return i;
    } else if (lyrics[i][1] >= audio.currentTime) {
      return i;
    }
  }
  return lyrics.length;
}

# Khi đoạn nhạc play, mình sẽ chạy một hàm interval. Hàm này liên tục cập nhật thời gian hiện tại của đoạn nhạc và tính toán thời gian bắt đầu, kết thúc của lời bài hát để cập nhật hiệu ứng highlight.

var lineIndex = 0;
var curentLyric, karaText, karaTextHighlight, audInterval;

// ...

audio.addEventListener('play', function () {
  audInterval = setInterval(function () {
    if (!curentLyric) {
      return;
    }

    var startTime = curentLyric[1];
    var endTime = curentLyric[2];

    if ((audio.currentTime - startTime) >= 0) {
      var duration = endTime - startTime;
      if (endTime - audio.currentTime > 0) {
        var ratio = ((100 / duration) * (endTime - audio.currentTime)) - 100;
        karaTextHighlight.style.width = ratio * -1 + '%';
      } else {
        lineIndex++;
        nextLine(lineIndex);
      }
    }
  }, 1000 / 60);
});

var nextLine = function (index) {
  if (!lyrics[lineIndex]) {
    return;
  }

  var lyric = lyrics[index];

  karaText.textContent = lyric[0];
  karaTextHighlight.textContent = lyric[0];
  karaTextHighlight.style.width = '0%';

  curentLyric = lyric;
}

# Còn cái hiệu ứng highlight text thì mình sẽ lợi dụng thuộc tính position của css để tạo ra hai thẻ p nằm chồng lên nhau. Hai thẻ p đều có cùng nội dung text và có kích thước font chữ giống nhau. Thẻ p nằm trên sẽ có màu khác với thẻ p nằm dưới và thay đổi độ dài theo thời gian mà đoạn lời bài hát xuất hiện để tạo hiệu ứng highlight.

#karaoke .kara-text,
#karaoke .kara-text-highlight {
  display: inline-block;
  font-size: 50px;
  white-space: nowrap;
}

#karaoke .kara-text {
  position: relative;
}

#karaoke .kara-text-highlight {
  position: absolute;
  top: 0;
  left: 0;
  color: violet;
  text-shadow: 0px 0px 20px violet;
  overflow: hidden;
}

2. Thành quả: Ứng dụng hát karaoke bằng HTML5-Audio

3. Lời kết

Qua ứng dụng hát karaoke bằng HTML5-Audio này, mình mong các bạn sẽ có thêm ý tưởng để làm nhiều cái hay ho hơn. Những lúc mệt mỏi, stress thì hãy làm những điều gì đó khiến bản thân cảm thấy vui vẻ và hứng thú trở lại nhé. Chúc các bạn thành công!

Lưu ý: Bài hát trong ví dụ là bài “Gọi Tên Em Trong Đêm – The Men“. Nếu link của bài hát trong ví dụ bị die thì phiền các bạn thay 1 link khác để xem được ví dụ nhé. Thanks all!

8 Comments

  1. Chào bạn
    Mình muốn hiện 2 dòng, một dòng chữ chạy phía trên và một dòng chữ chờ tiếp theo phía dưới thì làm thế nào ạ, bạn hướng dẫn giúp mình với nhé

      1. Bạn ơi! Có cách nào để highlight một đoạn văn bản theo audio khi mà “white-space: normal” không? Bạn hướng dẫn giúp mình với.

  2. Bạn có thể làm tính năng đọc file .lrc hoặc copy nội dung file .lrc vào chuỗi. Thay vì phải gõ thời gian trong chuỗi như vậy không tiện bạn à. Thanks

  3. Bạn có thể dùng lời .lrc có sẵn trên zingmp3.vn hoặc nhaccuatui.com với định dạng như sau:
    [00:01.47]Đừng khóc như thế
    [00:02.78]Xin đừng khóc như thế
    [00:04.53]Bao nhiêu niềm đau chôn dấu
    [00:06.60]Mong ngày sẽ trôi mau
    [00:08.55]Đời phong ba, độc thân bước chân Sơn Hà
    [00:14.11]
    [00:16.42]Buổi sáng hôm ấy
    [00:17.87]Khi còn trắng sương bay
    [00:19.55]Ta như là gió phiêu lãng
    [00:21.61]Mang hành lý thương nhớ
    [00:23.61]Chẳng sao đâu, sầu bi có khi còn lâu
    [00:30.55]Lạc mình trong cánh buồm phiêu du
    [00:33.80]Chiếc thuyền đong đưa
    [00:35.68]Những ngày xa xưa
    [00:37.68]Bé nhỏ hay thưa Mẹ thưa Cha
    [00:40.74]Rằng con đi học mới về
    [00:45.61]Giờ tung bay, khúc nhạc mê say
    [00:48.75]Nỗi lòng tha hương, vướng đường tương lai
    [00:52.58]Ước rằng ngày mai nắng lên
    [00:55.64]Ngày mai nắng lên ta sẽ quên
    [01:00.06]Này này này là em gì ơi
    [01:01.88]Em gì ơi, em gì ơi!
    [01:04.06]Ở lại và yêu được không
    [01:05.69]Yêu được không, yêu được không
    [01:07.94]Thật lòng này ta chỉ mong ta chỉ mong
    [01:10.31]Bên dòng sông, người có nhớ có trông ai…
    [01:15.56]Việc gì phải ôm buồn đau
    [01:16.92]Riêng mình ta riêng mình ta
    [01:19.09]Nụ cười nở muôn ngàn hoa
    [01:20.65]Muôn ngàn hoa, muôn ngàn hoa
    [01:22.84]Cuộc đời này thật là vui biết bao
    [01:25.78]Trời cao núi xanh mây ngàn sao
    [01:31.56]Khi bánh xe còn lăn bánh
    [01:33.25]Khi bánh xe còn lăn bánh
    [01:35.12]Ta xoay vòng với cuộc sống hối hả
    [01:36.72]Quên đi mộng ước thanh xuân đã trôi qua
    [01:38.55]Ta ngại va chạm khi nhiều lần dối trá
    [01:40.36]Những lần áp lực bởi công việc muốn đi xa
    [01:42.24]Vứt hết một lần trước khi nhìn đời thoái hóa
    [01:43.99]Tự do tự tại như chim trời và thi ca
    [01:45.74]Bước qua nà
    [01:49.79]Đời nhiều lúc cảm thấy rất nhiều trò
    [01:51.68]Thôi ta giang tay ôm lấy cả bầu trời!
    [01:53.43]Hỡi bạn thân ơi! Lá mù u rơi
    [01:55.19]Khát vọng ra khơi, chúng mình đi chơi
    [01:57.06]Bước thật hiên ngang, lối về thênh thang
    [01:58.93]Chẳng cần cao sang, nỗi lòng sang trang và từ nay
    [02:00.55]Lạc mình trong cánh buồm phiêu du
    [02:03.80]Chiếc thuyền đong đưa
    [02:05.68]Những ngày xa xưa
    [02:07.68]Bé nhỏ hay thưa Mẹ thưa Cha
    [02:10.74]Rằng con đi học mới về
    [02:15.61]Giờ tung bay, khúc nhạc mê say
    [02:18.75]Nỗi lòng tha hương, vướng đường tương lai
    [02:22.58]Ước rằng ngày mai nắng lên
    [02:25.64]Ngày mai nắng lên ta sẽ quên
    [02:30.06]Này này này là em gì ơi
    [02:31.88]Em gì ơi, em gì ơi!
    [02:34.06]Ở lại và yêu được không
    [02:35.69]Yêu được không, yêu được không
    [02:37.94]Thật lòng này ta chỉ mong ta chỉ mong
    [02:40.31]Bên dòng sông, người có nhớ có trông ai…
    [02:45.56]Việc gì phải ôm buồn đau
    [02:46.92]Riêng mình ta riêng mình ta
    [02:49.09]Nụ cười nở muôn ngàn hoa
    [02:50.65]Muôn ngàn hoa, muôn ngàn hoa
    [02:52.84]Cuộc đời này thật là vui biết bao
    [02:55.78]Trời cao núi xanh mây ngàn sao
    [03:00.26]Này này này là em gì ơi
    [03:02.08]Em gì ơi, em gì ơi!
    [03:04.26]Ở lại và yêu được không
    [03:05.89]Yêu được không, yêu được không
    [03:08.14]Thật lòng này ta chỉ mong ta chỉ mong
    [03:10.51]Bên dòng sông, người có nhớ có trông ai…
    [03:15.76]Việc gì phải ôm buồn đau
    [03:17.12]Riêng mình ta riêng mình ta
    [03:19.29]Nụ cười nở muôn ngàn hoa
    [03:20.85]Muôn ngàn hoa, muôn ngàn hoa
    [03:23.04]Cuộc đời này thật là vui biết bao
    [03:25.98]Trời cao núi xanh mây ngàn sao
    [03:30.67]
    Mình tận dụng luôn nguồn lời nhạc có sẵn. Bạn có thể làm thêm tính năng play playlist: tiến , lùi bài hát, lặp lại, ngẫu nhiên thì tuyệt vời luôn ^_^

Leave a Reply

Your email address will not be published. Required fields are marked *