Node.js中youtube.search.list返回id为[Object]的问题求助
Hey there! Let's fix that issue where you're seeing [Object] instead of the actual YouTube video ID in your Discord bot's play command.
The Root Cause
The id field in the YouTube API's search response isn't a plain string—it's an object that holds different ID types based on the result (video, channel, playlist). Since you're filtering for type: 'video', each result's id will have a videoId property that contains the exact YouTube video ID you need.
When you just run console.log(request), Node.js shorthands nested objects like id as [Object] to keep output concise. You need to explicitly access the nested property to get the actual ID string.
Modified Code Snippet
Here's how to adjust your run method to extract and log video IDs properly:
async run(message, args) { youtube.search.list({ maxResults: '5', part: 'snippet', type: 'video', q: args }, function (err, response) { if (err) { console.error('Error: ' + err); return; } // Check if there are any results returned if (!response.data.items || response.data.items.length === 0) { console.log('No video results found for your query'); return; } // Loop through each result to extract the video ID response.data.items.forEach(item => { const videoId = item.id.videoId; console.log(`Found video ID: ${videoId}`); // Bonus: You can also grab the video title with item.snippet.title }); }); }
Key Changes Explained
- Renamed
requesttoresponsefor clearer naming - Accessed
response.data.itemsinstead ofrequest.items—the Google API client wraps actual results in thedataproperty - Used
forEachto iterate through all 5 search results - Explicitly called
item.id.videoIdto get the string ID instead of the fullidobject - Added checks for errors and empty results to make the code more robust
Full Updated Command Class
If you want the complete, polished command code, here it is:
const commando = require('discord.js-commando'); const config = require(__dirname + "/../../config/settings.json"); const google = require('googleapis'); const ytdl = require('ytdl-core'); const youtube = google.youtube({ version: 'v3', auth: config.gapi }); class PlayCommand extends commando.Command { constructor(client) { super(client, { name: 'play', group: "music", memberName: 'play', description: 'Plays music from youtube', }); } async run(message, args) { youtube.search.list({ maxResults: '5', part: 'snippet', type: 'video', q: args }, function (err, response) { if (err) { console.error('Error: ' + err); return message.reply('Sorry, I couldn\'t search for that video right now.'); } if (!response.data.items || response.data.items.length === 0) { return message.reply('No videos found matching your query!'); } // Extract the first video ID (you can expand this to let users pick from results) const targetVideoId = response.data.items[0].id.videoId; console.log(`Preparing to play video with ID: ${targetVideoId}`); // Now you can use ytdl to stream the video: ytdl(`https://www.youtube.com/watch?v=${targetVideoId}`) }); } } module.exports = PlayCommand
This version also adds user-facing feedback in Discord, making the bot feel more responsive. You can even extend it later to let users choose which of the 5 results they want to play!
内容的提问来源于stack exchange,提问作者Wilchu

