You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js与Spotify API集成创建播放列表失败求助

问题排查:Spotify播放列表创建失败

我开发的Web应用可接收YouTube链接,识别视频中的歌曲并获取Spotify链接列表,但调用spotify.js接口创建播放列表时出现错误。已查看日志并尝试使用AI工具,仍未定位问题。链接转URI的函数逻辑自认为无误,请求协助排查潜在错误。

相关代码(spotify.js)

const express = require('express');
const axios = require('axios');
const querystring = require('querystring');
const router = express.Router();
require('dotenv').config();

const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
const userId = process.env.SPOTIFY_USER_ID;

let spotifyAccessToken = ''; // 由app.js动态设置
let spotifyRefreshToken = ''; // 由app.js动态设置

async function refreshAccessToken() {
    const authOptions = {
        url: 'https://accounts.spotify.com/api/token',
        form: {
            grant_type: 'refresh_token',
            refresh_token: spotifyRefreshToken
        },
        headers: {
            'Authorization': 'Basic ' + Buffer.from(client_id + ':' + client_secret).toString('base64')
        }
    };

    try {
        const response = await axios.post(authOptions.url, querystring.stringify(authOptions.form), {
            headers: authOptions.headers,
        });

        spotifyAccessToken = response.data.access_token;
        console.log('New Access Token:', spotifyAccessToken);
    } catch (error) {
        console.error('Error refreshing access token:', error);
    }
}

// 用于按需刷新token的中间件
router.use(async (req, res, next) => {
    if (!spotifyAccessToken) {
        await refreshAccessToken();
    }
    next();
});

// 将Spotify歌曲URL转换为URI的函数
function convertUrlsToUris(urls) {
    return urls.map(url => {
        const match = url.match(/track\/([^?\/]+)$/);
        if (match) {
            return `spotify:track:${match[1]}`;
        }
        throw new Error(`Invalid URL format: ${url}`);
    });
}

router.post('/create-playlist', async (req, res) => {
    const { spotifyLinks, youtubeLink, videoTitle } = req.body;
    const playlistName = videoTitle;

    try {
        // 创建新播放列表
        const createPlaylistResponse = await axios.post(
            `https://api.spotify.com/v1/users/${userId}/playlists`,
            {
                name: playlistName,
                description: 'Playlist created from YouTube video',
                public: false
            },
            {
                headers: {
                    'Authorization': `Bearer ${spotifyAccessToken}`,
                    'Content-Type': 'application/json'
                }
            }
        );

        const playlistId = createPlaylistResponse.data.id;
        console.log('Created Playlist ID:', playlistId);

        // 将歌曲URL转换为URI
        const trackUris = convertUrlsToUris(spotifyLinks);

        // 向播放列表添加歌曲
        if (trackUris && trackUris.length > 0) {
            const addTracksResponse = await axios.post(
                `https://api.spotify.com/v1/playlists/${playlistId}/tracks`,
                {
                    uris: trackUris
                },
                {
                    headers: {
                        'Authorization': `Bearer ${spotifyAccessToken}`,
                        'Content-Type': 'application/json'
                    }
                }
            );
            console.log('Tracks added to Playlist:', addTracksResponse.data);
        }

        res.json({ message: 'Playlist created successfully', playlistId });
    } catch (error) {
        console.error('Error creating playlist:', error.response ? error.response.data : error.message);
        res.status(500).json({ error: error.response ? error.response.data : 'Error creating playlist' });
    }
});

module.exports = router;

潜在错误排查方向

  • 权限缺失:确认Spotify授权流程中是否申请了playlist-modify-private(对应私有播放列表)权限,无此权限会直接导致创建失败。
  • AccessToken过期:当前中间件仅在token为空时刷新,但Spotify的access token有效期为1小时,过期后未触发刷新会导致请求失败。建议在每次请求前验证token有效期,或在请求返回401错误时自动刷新并重试。
  • 用户ID错误:检查SPOTIFY_USER_ID是否为正确的Spotify用户ID(不是用户名),可通过调用Spotify的/me接口获取准确ID。
  • 无效请求参数:确认videoTitle不为空(Spotify不允许名称为空的播放列表);检查spotifyLinks是否包含无效链接,转换函数抛出的错误会直接中断流程,需确保传入的链接格式正确。
  • 错误日志未完全输出:建议打印完整的错误响应(包括状态码、错误详情),比如401代表token无效,403代表权限不足,404代表用户ID不存在,这些信息能快速定位问题。
  • 刷新Token失败处理:refreshAccessToken函数刷新失败时未终止后续流程,会导致使用空token发起请求,需在刷新失败时返回错误响应,避免无效请求。

内容的提问来源于stack exchange,提问作者Whichman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 00:27:06