使用YouTube Data API v3、Vue/JS,如何检测并隐藏HTML中不可用的YouTube视频?
检测YouTube视频可用性并控制显示(Vue + JavaScript)
方法一:通过YouTube Data API v3预检测(推荐)
提前调用API验证视频状态,避免加载无效iframe,节省资源并提升用户体验。
核心检测逻辑
调用videos.list接口,指定part=status,contentDetails,重点检查以下字段:
status.uploadStatus:需为processed(视频已处理完成)status.privacyStatus:需为public(公开可访问)status.embeddable:需为true(允许嵌入)contentDetails.regionRestriction:若存在blocked列表,需确认用户所在地区不在其中
Vue组件示例代码
<template> <div class="youtube-videos"> <div v-for="videoId in availableVideoIds" :key="videoId" class="video-item"> <iframe :src="`https://www.youtube.com/embed/${videoId}`" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe> </div> </div> </template> <script> export default { data() { return { targetVideoIds: ['abc123', 'def456', 'ghi789'], // 你的视频ID列表 availableVideoIds: [], apiKey: '你的YouTube Data API密钥' } }, async mounted() { // 批量检测所有视频 const availabilityResults = await Promise.all( this.targetVideoIds.map(id => this.checkVideoValidity(id)) ) // 筛选出可用视频ID this.availableVideoIds = this.targetVideoIds.filter((_, index) => availabilityResults[index]) }, methods: { async checkVideoValidity(videoId) { try { const response = await fetch( `https://www.googleapis.com/youtube/v3/videos?id=${videoId}&part=status,contentDetails&key=${this.apiKey}` ) const data = await response.json() // 视频不存在直接返回不可用 if (!data.items || data.items.length === 0) return false const { status, contentDetails } = data.items[0] // 基础可用性校验 if (status.uploadStatus !== 'processed' || status.privacyStatus !== 'public' || !status.embeddable) { return false } // 地区限制校验(可选,需自行获取用户地区) if (contentDetails.regionRestriction?.blocked) { // 示例:通过IP接口获取用户地区,这里假设为'CN' const userRegion = 'CN' if (contentDetails.regionRestriction.blocked.includes(userRegion)) { return false } } return true } catch (err) { console.error(`检测视频${videoId}失败:`, err) return false } } } } </script>
方法二:iframe加载后监听错误
部分临时屏蔽或API未覆盖的情况,可通过iframe的错误事件兜底检测。YouTube嵌入iframe支持enablejsapi=1参数开启JS接口,通过postMessage接收错误信息。
Vue组件示例代码
<template> <div class="youtube-videos"> <div v-for="videoId in targetVideoIds" :key="videoId" class="video-item"> <iframe :src="`https://www.youtube.com/embed/${videoId}?enablejsapi=1`" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ref="youtubeIframes" @load="initIframeListener(videoId)" ></iframe> </div> </div> </template> <script> export default { data() { return { targetVideoIds: ['abc123', 'def456', 'ghi789'], unavailableVideos: new Set() } }, mounted() { // 监听YouTube iframe发送的消息 window.addEventListener('message', this.handleYouTubeMessage) }, beforeUnmount() { // 组件销毁前移除监听,避免内存泄漏 window.removeEventListener('message', this.handleYouTubeMessage) }, methods: { initIframeListener(videoId) { // 找到对应iframe并发送监听请求 const iframe = this.$refs.youtubeIframes.find(el => el.src.includes(videoId)) if (iframe) { iframe.contentWindow.postMessage( { event: 'listening', id: videoId }, 'https://www.youtube.com' ) } }, handleYouTubeMessage(event) { // 验证消息来源,防止跨域攻击 if (event.origin !== 'https://www.youtube.com') return const { event: msgEvent, infoCode, id } = event.data // 处理错误事件:100=视频不存在,101/150=无法嵌入/地区限制 if (msgEvent === 'error' && [100, 101, 150].includes(infoCode)) { this.unavailableVideos.add(id) // 隐藏不可用的iframe const iframe = this.$refs.youtubeIframes.find(el => el.src.includes(id)) if (iframe) iframe.style.display = 'none' } } } } </script>
注意事项
- API配额限制:YouTube Data API有调用配额限制,批量检测时注意控制请求频率,避免超出配额。
- 地区检测准确性:用户地区可通过IP查询接口获取,比浏览器定位更可靠。
- 组合使用:建议先通过API预检测,再用iframe错误监听兜底,兼顾性能和准确性。
内容的提问来源于stack exchange,提问作者Kutay Avcı
相关产品推荐
相关产品推荐

