礼貌是儿童和青年都应该特别小心地养成习惯的第一件大事——约翰·洛克
先放代码:
<script>
/**
*
* @param src string 视频url
* @param currentTime double 视频截取位置,单位秒
* @return 截取图片的 base64
*/
function getImgFromVideoUrl(src, currentTime) {
if (!src) return
if (!currentTime || currentTime < 0) {
// 如果传入截取位置小于0, 给个默认值
currentTime = 0.001
}
return new Promise(resolve => {
const body = document.querySelector("body")
// 获取/创建video节点
const video = document.querySelector("#imgExtractorVideo") || document.createElement("video")
if (!video.id) {
// id,隐藏样式
Object.assign(video, {
id: 'imgExtractorVideo',
style: "display: none"
})
// 允许跨域
video.setAttribute('crossorigin', 'anonymous')
// 添加到页面上,下次就不用创建,直接用
body.append(video)
}
// 此处给video赋值,canplay需要重新赋值,否则load后不会重复调用
Object.assign(video, { src, currentTime, oncanplay })
// 获取/创建canvas节点
const canvas = document.querySelector("#imgExtractorCanvas") || document.createElement("canvas")
if (!canvas.id) {
// id,隐藏样式
Object.assign(canvas, {
id: 'imgExtractorCanvas',
style: "display: none"
})
// 添加到页面上,下次就不用创建,直接用
body.append(canvas)
}
// 获取canvas context
const context = canvas.getContext("2d")
// canvas渲染视频节点,转换为base64
async function oncanplay() {
// 为canvas设置宽高为视频的宽高
Object.assign(canvas, { height: video.videoHeight, width: video.videoWidth })
// 渲染视频
context.drawImage(video, 0, 0)
// 获取视频时长
const duration = isNaN(video.duration) ? 0 : video.duration
if (currentTime > duration) {
// 如果当前传入截取位置大于视频时长,取视频时长 -0.1 然后重新截取
currentTime = duration - 0.1;
resolve(await getImgFromVideoUrl(src, currentTime))
} else {
// 这里的 toDataURL 第二个参数为图片质量,可接受范围 0~1 ,超出后为默认值 0.92
resolve(canvas.toDataURL("image/png", 1.0))
}
}
})
}
window.onload = async () => {
// 视频长度 15s 左右
// 调用
let imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4")
// 使用
console.log({ imgBase64 })
let img = document.createElement("img")
img.src = imgBase64
document.querySelector("body").append(img)
// 调用
imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 3)
// 重复使用
console.log({ imgBase64 })
img = document.createElement("img")
img.src = imgBase64
document.querySelector("body").append(img)
// 调用
imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 4)
// 重复使用
console.log({ imgBase64 })
img = document.createElement("img")
img.src = imgBase64
document.querySelector("body").append(img)
// 调用
imgBase64 = await getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 20)
// 重复使用
console.log({ imgBase64 })
img = document.createElement("img")
img.src = imgBase64
document.querySelector("body").append(img)
// Promise回调地狱
getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 3)
.then(base64 => {
// 使用
console.log({ base64 })
let img = document.createElement("img")
img.src = base64
document.querySelector("body").append(img)
// Promise回调地狱
getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 4)
.then(base64 => {
// 使用
console.log({ base64 })
let img = document.createElement("img")
img.src = base64
document.querySelector("body").append(img)
// Promise回调地狱
getImgFromVideoUrl("https://waibi.oss-cn-chengdu.aliyuncs.com/picGo/rabbit.mp4", 5)
.then(base64 => {
// 使用
console.log({ base64 })
let img = document.createElement("img")
img.src = base64
document.querySelector("body").append(img)
})
})
})
}
</script>效果:

接下来是博客和MDN:
Promise博客:https://cloud.tencent.com/developer/article/2075561
oss视频截封面博客:https://vampireachao.gitee.io/2022/01/10/oss视频截封面/
MDN:
Promise:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promisedocument.querySelector:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/querySelectordocument.createElement:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElementObject.assign:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assignelement.setAttribute:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/setAttributeelement.append:https://developer.mozilla.org/zh-CN/docs/Web/API/Element/appendHTMLCanvasElement.getContext:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/getContextcanplay currentTime videoHeight duration等API的介绍,通过document.querySelector("#imgExtractorVideo")或者是document.createElement("video")返回的HTMLMediaElement:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElementvideo标签:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/videocanvas:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_APIasync函数:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_functionawait:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/awaitcanvas使用图像:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Using_imagesisNaN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/isNaNgetContext toDataURL等API的介绍,通过document.querySelector("#imgExtractorCanvas")或者document.createElement("canvas")返回的HTMLCanvasElement:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement
如果我们Base64需要下载,可以参考:blob和base64互转