How do I get a YouTube video thumbnail from the YouTube API?

后端 未结 30 3262
Happy的楠姐
Happy的楠姐 2020-11-21 07:06

If I have a YouTube video URL, is there any way to use PHP and cURL to get the associated thumbnail from the YouTube API?

30条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-21 07:43

    This is my client-side-only no-API-key-required solution.

    YouTube.parse('https://www.youtube.com/watch?v=P3DGwyl0mJQ').then(_ => console.log(_))
    

    The code:

    import { parseURL, parseQueryString } from './url'
    import { getImageSize } from './image'
    
    const PICTURE_SIZE_NAMES = [
        // 1280 x 720.
        // HD aspect ratio.
        'maxresdefault',
        // 629 x 472.
        // non-HD aspect ratio.
        'sddefault',
        // For really old videos not having `maxresdefault`/`sddefault`.
        'hqdefault'
    ]
    
    // - Supported YouTube URL formats:
    //   - http://www.youtube.com/watch?v=My2FRPA3Gf8
    //   - http://youtu.be/My2FRPA3Gf8
    export default
    {
        parse: async function(url)
        {
            // Get video ID.
            let id
            const location = parseURL(url)
            if (location.hostname === 'www.youtube.com') {
                if (location.search) {
                    const query = parseQueryString(location.search.slice('/'.length))
                    id = query.v
                }
            } else if (location.hostname === 'youtu.be') {
                id = location.pathname.slice('/'.length)
            }
    
            if (id) {
                return {
                    source: {
                        provider: 'YouTube',
                        id
                    },
                    picture: await this.getPicture(id)
                }
            }
        },
    
        getPicture: async (id) => {
            for (const sizeName of PICTURE_SIZE_NAMES) {
                try {
                    const url = getPictureSizeURL(id, sizeName)
                    return {
                        type: 'image/jpeg',
                        sizes: [{
                            url,
                            ...(await getImageSize(url))
                        }]
                    }
                } catch (error) {
                    console.error(error)
                }
            }
            throw new Error(`No picture found for YouTube video ${id}`)
        },
    
        getEmbeddedVideoURL(id, options = {}) {
            return `https://www.youtube.com/embed/${id}`
        }
    }
    
    const getPictureSizeURL = (id, sizeName) => `https://img.youtube.com/vi/${id}/${sizeName}.jpg`
    

    Utility image.js:

    // Gets image size.
    // Returns a `Promise`.
    function getImageSize(url)
    {
        return new Promise((resolve, reject) =>
        {
            const image = new Image()
            image.onload = () => resolve({ width: image.width, height: image.height })
            image.onerror = reject
            image.src = url
        })
    }
    

    Utility url.js:

    // Only on client side.
    export function parseURL(url)
    {
        const link = document.createElement('a')
        link.href = url
        return link
    }
    
    export function parseQueryString(queryString)
    {
        return queryString.split('&').reduce((query, part) =>
        {
            const [key, value] = part.split('=')
            query[decodeURIComponent(key)] = decodeURIComponent(value)
            return query
        },
        {})
    }
    

提交回复
热议问题