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ò 😉👇
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_ID
và SPOTIFY_CLIENT_SECRET
Đăng nhập Spotify Developer Dashboard
- Truy cập Spotify Developer Dashboard và đăng nhập bằng tài khoản Spotify của bạn.
- Trong phần Dashboard, chọn "Create app" để tạo một ứng dụng mới.
Tạo Ứng Dụng Mới
- Điền thông tin yêu cầu như tên ứng dụng và mô tả.
- 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.
Lấy Client ID
và Client Secret
- Chọn "Settings" để lấy
Client ID
vàClient Secret
.
- 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 ID
vàClient 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
- 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
- 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
- Thay thế
YOUR_CLIENT_ID
bằngClient ID
bạn đã lấy ở bước trước vàYOUR_REDIRECT_URI
bằngRedirect URI
bạn đã cấu hình.
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
- Mã hoá Client ID và Client Secret thành Base64 bằng công cụ trực tuyến như Base64 Encode.
- 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
- 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
- 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.
- 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.
- 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.
- 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.
- album: Thông tin chi tiết về album chứa bài hát.
- currently_playing_type:
"track"
- Loại nội dung đang phát (trong trường hợp này là bài hát).
- 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.
- 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.
- 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
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