+8

Chia Sẻ Trực Tiếp Bài Hát Đang Nghe Lên Website Với Spotify API

Trong bài viết này, mình sẽ giới thiệu cách mình đã sử dụng sử dụng Spotify API kết hợp với Next.js để tạo một phần footer hiển thị thông tin bài hát đang phát. Sau khi làm theo các bước trong bài này bạn sẽ có một phần footer với bài hát bạn đang nghe trên Spotify của mình thật xịn xò 😉👇 cuongday.com - Lâm Phú Cường portfolio footer

Spotify API cung cấp các endpoint để lấy thông tin về bài hát đang phát trên tài khoản của bạn và nhiều thông tin khác, nhưng trong phần này mình chỉ tập trung vào việc lấy tên bài hát và tên artist.

Để thực hiện việc này, chúng ta cần sử dụng ba biến môi trường:

  • SPOTIFY_CLIENT_ID
  • SPOTIFY_CLIENT_SECRET
  • SPOTIFY_REFRESH_TOKEN

Ba biến này sẽ giúp xác thực và lấy token truy cập cần thiết để gọi API của Spotify.

Bước 1: Lấy SPOTIFY_CLIENT_IDSPOTIFY_CLIENT_SECRET

Đăng nhập Spotify Developer Dashboard

  1. Truy cập Spotify Developer Dashboard và đăng nhập bằng tài khoản Spotify của bạn.

Logged In

  1. Trong phần Dashboard, chọn "Create app" để tạo một ứng dụng mới.

Create App Spotify API

Tạo Ứng Dụng Mới

  1. Điền thông tin yêu cầu như tên ứng dụng và mô tả.

Enter Appinfo to the Spotify API App

  1. Nhấn nút "Save" để lưu và tạo ứng dụng mới. Sau khi nhập đầy đủ các thông tin được yêu cầu và nhấn nút save tạo ứng dụng thành công bạn sẽ được chuyển đến trang dashboard của ứng dụng vừa tạo. Spotify API App Dashboard

Lấy Client IDClient Secret

  1. Chọn "Settings" để lấy Client IDClient Secret.

How to get Client ID and Client Secret in Spotify API ?

  • lưu ý: Bạn sẽ cần các giá trị này ở các bước sau nên hãy lưu lại Client IDClient Secret.

Bước 2: Lấy SPOTIFY_REFRESH_TOKEN

Để lấy Refresh Token, bạn cần thực hiện một vài bước bổ sung để xác thực người dùng và lấy token.

Cấu hình Redirect URI

  1. Trong trang quản lý ứng dụng của bạn trên Spotify Developer Dashboard, thêm một Redirect URI trong mục "Settings". Ví dụ: http://localhost:3000/callback.

Lấy Authorization Code

  1. Truy cập đường dẫn sau trên trình duyệt để lấy mã Authorization Code:

https://accounts.spotify.com/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=user-read-currently-playing

  1. Thay thế YOUR_CLIENT_ID bằng Client ID bạn đã lấy ở bước trước và YOUR_REDIRECT_URI bằng Redirect URI bạn đã cấu hình.

image.png

Bạn sẽ được chuyển hướng đến trang đăng nhập của Spotify và yêu cầu cấp quyền cho ứng dụng. Sau khi cấp quyền, bạn sẽ được chuyển hướng đến Redirect URI với một mã Authorization Code trên URL.

Đổi Authorization Code lấy Refresh Token

  1. Mã hoá Client ID và Client Secret thành Base64 bằng công cụ trực tuyến như Base64 Encode.
  2. Sử dụng chuỗi mã hóa trong lệnh curl sau để lấy Refresh Token:
bashCopy code
curl -X POST -H "Authorization: Basic EN_CODED_STRING" -d "grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI" https://accounts.spotify.com/api/token

Thay thế:

  • EN_CODED_STRING bằng chuỗi bạn nhận được nhờ mã hóa.
  • AUTHORIZATION_CODE bằng mã Authorization Code bạn đã nhận được.
  • YOUR_REDIRECT_URI bằng Redirect URI bạn đã cấu hình.

Nếu thành công, bạn sẽ nhận được một JSON response chứa access_token, token_type, expires_in, và refresh_token. Lưu lại giá trị của refresh_token để sử dụng ở các bước sau.

Kiểm Tra Refresh Token

  1. Sử dụng lệnh curl sau để kiểm tra Refresh Token:
curl -X POST -H "Authorization: Basic EN_CODED_STRING" -d "grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN" https://accounts.spotify.com/api/token

Thay thế EN_CODED_STRING bằng chuỗi bạn nhận được nhờ mã hóa và YOUR_REFRESH_TOKEN bằng giá trị refresh_token bạn đã nhận được. Nếu lệnh này trả về một access_token, điều đó có nghĩa là Refresh Token của bạn hoạt động tốt.

Kết Quả Mong Đợi

Nếu lệnh trên thành công, bạn sẽ nhận được phản hồi JSON chứa một access_token mới, giống như sau:

code
{
    "access_token": "new_access_token",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "user-read-currently-playing"
}

Sử Dụng access_token Để Lấy Thông Tin Bài Hát Đang Phát

Lấy thông tin bài hát đang phát:


curl -X GET "https://api.spotify.com/v1/me/player/currently-playing" -H "Authorization: Bearer new_access_token"

Thay thế new_access_token bằng giá trị access_token mới mà bạn vừa nhận được.

Kiểm Tra Kết Quả Trả Về

Phản hồi sẽ chứa thông tin về bài hát đang phát nếu có bài hát nào đang phát, hoặc thông báo lỗi nếu không có bài hát nào đang phát.

Ví dụ:


C:\Users\PC>curl -X GET "https://api.spotify.com/v1/me/player/currently-playing" -H "Authorization: Bearer [Hidden]"
{
  "timestamp": 1721922595726,
  "context": {
    "external_urls": {
      "spotify": "https://open.spotify.com/album/1c4nTHI2hreFeF5P37wf4f"
    },
    "href": "https://api.spotify.com/v1/albums/1c4nTHI2hreFeF5P37wf4f",
    "type": "album",
    "uri": "spotify:album:1c4nTHI2hreFeF5P37wf4f"
  },
  "progress_ms": 25715,
  "item": {
    "album": {
      "album_type": "single",
      "artists": [{
        "external_urls": {
          "spotify": "https://open.spotify.com/artist/1nX1HVIUo1Zfs3e2v3lFb9"
        },
        "href": "https://api.spotify.com/v1/artists/1nX1HVIUo1Zfs3e2v3lFb9",
        "id": "1nX1HVIUo1Zfs3e2v3lFb9",
        "name": "Changg",
        "type": "artist",
        "uri": "spotify:artist:1nX1HVIUo1Zfs3e2v3lFb9"
      }],
      "available_markets": [...],
      "external_urls": {
        "spotify": "https://open.spotify.com/album/6sUgmtdrcZRJxRsfbxUxqc"
      },
      "href": "https://api.spotify.com/v1/albums/6sUgmtdrcZRJxRsfbxUxqc",
      "id": "6sUgmtdrcZRJxRsfbxUxqc",
      "images": [{
        "height": 640,
        "url": "https://i.scdn.co/image/ab67616d0000b27330ad4af2a51dfd2e4dc5550f",
        "width": 640
      }, {
        "height": 300,
        "url": "https://i.scdn.co/image/ab67616d00001e0230ad4af2a51dfd2e4dc5550f",
        "width": 300
      }, {
        "height": 64,
        "url": "https://i.scdn.co/image/ab67616d0000485130ad4af2a51dfd2e4dc5550f",
        "width": 64
      }],
      "name": "Hướng Dương",
      "release_date": "2021-05-20",
      "release_date_precision": "day",
      "total_tracks": 1,
      "type": "album",
      "uri": "spotify:album:6sUgmtdrcZRJxRsfbxUxqc"
    },
    "artists": [{
      "external_urls": {
        "spotify": "https://open.spotify.com/artist/1nX1HVIUo1Zfs3e2v3lFb9"
      },
      "href": "https://api.spotify.com/v1/artists/1nX1HVIUo1Zfs3e2v3lFb9",
      "id": "1nX1HVIUo1Zfs3e2v3lFb9",
      "name": "Changg",
      "type": "artist",
      "uri": "spotify:artist:1nX1HVIUo1Zfs3e2v3lFb9"
    }],
    "available_markets": [...],
    "disc_number": 1,
    "duration_ms": 219212,
    "explicit": false,
    "external_ids": {
      "isrc": "SGUM72100220"
    },
    "external_urls": {
      "spotify": "https://open.spotify.com/track/65uxT4ZGe6eOABj1g5V2Fj"
    },
    "href": "https://api.spotify.com/v1/tracks/65uxT4ZGe6eOABj1g5V2Fj",
    "id": "65uxT4ZGe6eOABj1g5V2Fj",
    "is_local": false,
    "name": "Hướng Dương",
    "popularity": 49,
    "preview_url": null,
    "track_number": 1,
    "type": "track",
    "uri": "spotify:track:65uxT4ZGe6eOABj1g5V2Fj"
  },
  "currently_playing_type": "track",
  "actions": {
    "disallows": {
      "resuming": true,
      "toggling_repeat_context": true,
      "toggling_repeat_track": true,
      "toggling_shuffle": true
    }
  },
  "is_playing": true
}

Giải Thích Kết Quả Trả Về Nếu Có Bài Hát Đang Phát

  1. timestamp: 1721922595726
    • Dấu thời gian của phản hồi, thể hiện thời điểm yêu cầu được thực hiện.
  2. context
    • external_urls: Chứa URL mở album trên Spotify.
    • href: Liên kết đến API của album.
    • type: Loại context (trong trường hợp này là "album").
    • uri: URI của album trên Spotify.
  3. progress_ms: 25715
    • Thời gian đã phát của bài hát hiện tại, tính bằng mili giây.
  4. item
    • album: Thông tin chi tiết về album chứa bài hát.
      • album_type: Loại album (ví dụ: single).
      • artists: Danh sách nghệ sĩ của album.
      • available_markets: Các thị trường mà album có sẵn.
      • external_urls: URL mở album trên Spotify.
      • href: Liên kết đến API của album.
      • id: ID của album trên Spotify.
      • images: Danh sách ảnh bìa của album ở các độ phân giải khác nhau.
      • name: Tên album.
      • release_date: Ngày phát hành album.
      • release_date_precision: Độ chính xác của ngày phát hành.
      • total_tracks: Tổng số bài hát trong album.
      • type: Loại (trong trường hợp này là "album").
      • uri: URI của album trên Spotify.
    • artists: Danh sách nghệ sĩ của bài hát.
      • external_urls: URL mở trang nghệ sĩ trên Spotify.
      • href: Liên kết đến API của nghệ sĩ.
      • id: ID của nghệ sĩ trên Spotify.
      • name: Tên nghệ sĩ.
      • type: Loại (trong trường hợp này là "artist").
      • uri: URI của nghệ sĩ trên Spotify.
    • available_markets: Các thị trường mà bài hát có sẵn.
    • disc_number: Số đĩa của bài hát trong album.
    • duration_ms: Thời lượng của bài hát, tính bằng mili giây.
    • explicit: Cho biết bài hát có chứa nội dung nhạy cảm hay không.
    • external_ids: Chứa mã nhận dạng quốc tế của bài hát (ISRC).
    • external_urls: URL mở bài hát trên Spotify.
    • href: Liên kết đến API của bài hát.
    • id: ID của bài hát trên Spotify.
    • is_local: Cho biết bài hát có phải là bài hát cục bộ không.
    • name: Tên bài hát.
    • popularity: Độ phổ biến của bài hát.
    • preview_url: URL để nghe thử bài hát (có thể là null nếu không có).
    • track_number: Số thứ tự của bài hát trong album.
    • type: Loại (trong trường hợp này là "track").
    • uri: URI của bài hát trên Spotify.
  5. currently_playing_type: "track"
    • Loại nội dung đang phát (trong trường hợp này là bài hát).
  6. actions
    • disallows: Các hành động không được phép thực hiện trong quá trình phát hiện tại.
      • resuming: Không cho phép tiếp tục phát.
      • toggling_repeat_context: Không cho phép thay đổi chế độ lặp lại toàn bộ playlist/album.
      • toggling_repeat_track: Không cho phép thay đổi chế độ lặp lại bài hát.
      • toggling_shuffle: Không cho phép bật/tắt chế độ phát ngẫu nhiên.
  7. is_playing: true
    • Cho biết Spotify đang phát nhạc.

Bước 3: Tạo dự án Next.js mới

Tạo dự án Next.js

Sử dụng pnpm để tạo dự án Next.js:

pnpm create next-app spotify-now-playing --ts
cd spotify-now-playing
  • lưu ý: ở đây mình sử dụng pnpm, tuy nhiên bạn cũng có thể sử dụng bất kỳ trình quản lý gói khác như npm, yarn ,...

Cài đặt các package cần thiết

Cài đặt axios ( hoặc bất cứ thư viện, công cụ khác tương tự như Axios, miễn là nó có thể giúp bạn thực hiện các yêu cầu HTTP) để gọi API:

pnpm add axios

Thiết lập các biến môi trường

Tạo một tệp .env.local trong thư mục gốc của dự án và thêm các biến môi trường:

SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
SPOTIFY_REFRESH_TOKEN=your_spotify_refresh_token

Bước 4: Tạo API để lấy bài hát đang phát

Tạo một tệp pages/api/spotify.ts:

import type { NextApiRequest, NextApiResponse } from 'next'
import axios from 'axios'

const {
  SPOTIFY_CLIENT_ID,
  SPOTIFY_CLIENT_SECRET,
  SPOTIFY_REFRESH_TOKEN,
} = process.env

const basic = Buffer.from(`${SPOTIFY_CLIENT_ID}:${SPOTIFY_CLIENT_SECRET}`).toString('base64')
const TOKEN_ENDPOINT = 'https://accounts.spotify.com/api/token'
const NOW_PLAYING_ENDPOINT = 'https://api.spotify.com/v1/me/player/currently-playing'

const getAccessToken = async () => {
  const response = await axios.post(
    TOKEN_ENDPOINT,
    new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: SPOTIFY_REFRESH_TOKEN!,
    }),
    {
      headers: {
        Authorization: `Basic ${basic}`,
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    }
  )

  return response.data.access_token
}

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const accessToken = await getAccessToken()

  const response = await axios.get(NOW_PLAYING_ENDPOINT, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  })

  if (response.status === 204 || response.status > 400) {
    return res.status(200).json({ isPlaying: false })
  }

  const song = response.data

  res.status(200).json({
    isPlaying: song.is_playing,
    title: song.item.name,
    artist: song.item.artists.map((artist: { name: string }) => artist.name).join(', '),
    album: song.item.album.name,
    albumImageUrl: song.item.album.images[0].url,
    songUrl: song.item.external_urls.spotify,
  })
}

Bước 5: Tạo component NowPlaying

Tạo một tệp components/NowPlaying.tsx:

import useSWR from 'swr'
import axios from 'axios'

const fetcher = (url: string) => axios.get(url).then(res => res.data)

const NowPlaying = () => {
  const { data } = useSWR('/api/spotify', fetcher, {
    refreshInterval: 30000,
  })

  if (!data) return <div>Loading...</div>if (!data.isPlaying) return <div>Not Playing</div>

  return (
    <div className="flex items-center gap-4">
      <img
        src={data.albumImageUrl}
        alt={data.title}
        className="object-cover w-16 h-16"
      />
      <div className="flex flex-col">
        <a href={data.songUrl} target="_blank" rel="noopener noreferrer">
          {data.title}
        </a>
        <p>{data.artist}</p>
        <p>{data.album}</p>
      </div>
    </div>
  )
}

export default NowPlaying

Bước 6: Tạo component Footer

Tạo một tệp components/Footer.tsx:

import NowPlaying from './NowPlaying'

const Footer = () => {
  return (
    <footer className="bg-gray-800 text-white p-4">
      <NowPlaying />
    </footer>
  )
}

export default Footer

Bước 7: Sử dụng Footer trong ứng dụng

Sửa đổi tệp pages/_app.tsx để bao gồm Footer:

import '../styles/globals.css'
import type { AppProps } from 'next/app'
import Footer from '../components/Footer'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <div className="min-h-screen flex flex-col">
      <main className="flex-grow">
        <Component {...pageProps} />
      </main>
      <Footer />
    </div>
  )
}

export default MyApp

Bước 8: Thêm CSS tùy chỉnh

Tạo tệp styles/globals.css nếu chưa có và thêm CSS tùy chỉnh:

body {
  @apply bg-gray-900 text-white;
}

footer {
  @apply flex flex-col items-center justify-center;
}

Bước 9: Chạy ứng dụng

Chạy ứng dụng Next.js:


pnpm dev

Mở trình duyệt và truy cập http://localhost:3000 để xem kết quả.

Hoàn Thành

Vậy là ta đã cùng nhau hoàn thành việc tích hợp Spotify API với Next.js để hiển thị bài hát đang phát trên website cá nhân của mình. Bây giờ bạn hãy thử tưởng tượng xem mỗi khi khách truy cập vào trang, họ sẽ biết ngay bạn đang "quẩy" bài gì! 😄

Tham Khảo

Spotify Developer Dashboard.

Spotify API Documentation.

Next.js Documentation.

Base64 Encode. Công cụ mã hóa Base64.

Axios. Thư viện JavaScript để thực hiện các yêu cầu HTTP.

Từ Tác Giả

Mọi đóng góp để bài viết chính xác hơn đều rất quý giá, nếu phát hiện có lỗi sai trong bài viết hoặc khó khăn trong quá tình thực hiện, hãy để lại bình luận hoặc liên hệ với mình thông qua các kênh liên hệ của mình trong phần phần "Connect" tại cuongday.com

Chúc bạn thành công và nếu thấy hữu ích hãy cho mình 1 upvote và 1 follow nhé, thank you 💖🎓 !


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí