前端 ——youtube、tiktok视频封面获取并使用canvas合并封面和自定义播放按钮生成图片

⭐前言

大家好,我是yma16,本文分享 前端 ——youtube、tiktok视频封面获取并使用canvas合并封面和自定义播放按钮生成图片。

canvas 绘制图片

Canvas是HTML5提供的一个可以使用脚本(通常是JavaScript)进行绘图的元素。它可以用来在网页上实现各种复杂的图形和动画效果,比如绘制图形、处理图像、创建动画等。

Canvas提供了一组绘图API,可以通过JavaScript来控制绘图过程,包括绘制形状、文本、图像,以及对绘图对象进行变换、动画和交互等操作。Canvas的绘图效果是即时的,也就是说图形不是预先生成的,而是在用户加载网页时实时绘制的。

使用Canvas可以实现许多有趣和交互性强的效果,比如数据可视化、图表绘制、游戏开发等。同时,Canvas也可以与CSS、HTML元素和其他JavaScript库结合使用,为网页添加更加丰富的视觉效果。

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/canvas
node系列往期文章
node_windows环境变量配置
node_npm发布包
linux_配置node
node_nvm安装配置
node笔记_http服务搭建(渲染html、json)
node笔记_读文件
node笔记_写文件
node笔记_连接mysql实现crud
node笔记_formidable实现前后端联调的文件上传
node笔记_koa框架介绍
node_koa路由
node_生成目录
node_读写excel
node笔记_读取目录的文件
node笔记——调用免费qq的smtp发送html格式邮箱
node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)
node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)
node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)

koa系列项目文章
前端vite+vue3结合后端node+koa——实现代码模板展示平台(支持模糊搜索+分页查询)
node+vue3+mysql前后分离开发范式——实现对数据库表的增删改查
node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

koa-vue性能监控到封装sdk系列文章
性能监控系统搭建——node_koa实现性能监控数据上报(第一章)
性能监控系统搭建——vue3实现性能监控数据展示(第二章)
性能监控计算——封装带性能计算并上报的npm包(第三章)
canvas系列文章
web canvas系列——快速入门上手绘制二维空间点、线、面
webgl canvas系列——快速加背景、抠图、加水印并下载图片
webgl canvas系列——animation中基本旋转、平移、缩放(模拟冒泡排序过程)
前端vue系列文章
vue3 + fastapi 实现选择目录所有文件自定义上传到服务器
前端vue2、vue3去掉url路由“ # ”号——nginx配置
csdn新星计划vue3+ts+antd赛道——利用inscode搭建vue3(ts)+antd前端模板
认识vite_vue3 初始化项目到打包
python_selenuim获取csdn新星赛道选手所在城市用echarts地图显示
让大模型分析csdn文章质量 —— 提取csdn博客评论在文心一言分析评论区内容
前端vue3——html2canvas给网站截图生成宣传海报
前端——html拖拽原理
前端 富文本编辑器原理——从javascript、html、css开始入门
前端老古董execCommand——操作 选中文本 样式
前端如何在30秒内实现吸管拾色器?
前端——原生Selection api操作选中文本 样式、取消样式(解决标签的无限嵌套问题)
前端 ——xml转json json转xml 实现 mjml 邮件内容转json,json转mjml

⭐获取youtube 封面

根据youtube 视频链接 提前视频id
组装封面url

  // 获取 YouTube 封面
  const getYouTubeCover = (videoUrl: string) => {
    try {
      let videoId: any = "";
      // https://youtu.be/ERZBOxBoBCo?si=VIc6I0RLC7ucmfUq  分享链接
      if (videoUrl.startsWith("https://youtu.be/")) {
        videoId = videoUrl.split("https://youtu.be/")[1].split("?")[0];
      } else if (videoUrl.startsWith("https://www.youtube.com/watch?")) {
        //https://www.youtube.com/watch?v=ERZBOxBoBCo
        videoId = videoUrl.match(/v=([^&]+)/)?.[1] || videoUrl.split("/").pop();
      } else if (videoUrl.startsWith("https://www.youtube.com/shorts/")) {
        // https://www.youtube.com/shorts/iYKfzQw_zVM
        videoId = videoUrl
          .split("https://www.youtube.com/shorts/")[1]
          .split("?")[0];
      }
      const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`;
      setYoutubeVideoCoverUrl(thumbnailUrl);
      return thumbnailUrl;
    } catch (error) {
      setYoutubeVideoCoverUrl("");
      throw new Error(`YouTube Error: ${error}`);
    }
  };

⭐获取tiktok封面

通过开放的api请求 tiktok封面

 // 获取 tiktok 封面
  const gettiktokCover = async (videoUrl: string) => {
    try {
      // 拼接oEmbed请求地址
      const apiUrl = `https://www.tiktok.com/oembed?url=${encodeURIComponent(videoUrl)}`;

      // 发送跨域请求(需后端代理或启用CORS)
      const response = await axios.get(apiUrl);
      const data = response.data;

      // 返回封面图URL[1](@ref)
      setTiktokVideoCoverUrl(data.thumbnail_url);
      return data.thumbnail_url;
    } catch (error) {
      setTiktokVideoCoverUrl("");
      throw new Error(`tiktok Error: ${error}`);
    }
  };

⭐canvas合并图片

使用canvas drawImage api 绘制图片,主要处理绘制中心位置

function mergeCoverWithButton(coverUrl: string, buttonUrl: string) {
  return new Promise((resolve, reject) => {
    // 创建 Canvas 元素
    const canvas = document.createElement("canvas");
    const ctx: any = canvas.getContext("2d");

    //@ts-ignore 加载图片资源
    const coverImg = document.createElement("img");
    //@ts-ignore
    const buttonImg = document.createElement("img");
    coverImg.crossOrigin = buttonImg.crossOrigin = "anonymous"; // 处理跨域[2,4](@ref)

    // 封面加载完成
    coverImg.onload = () => {
      // 设置 Canvas 尺寸匹配封面
      canvas.width = coverImg.naturalWidth;
      canvas.height = coverImg.naturalHeight;

      // 绘制封面
      ctx.drawImage(coverImg, 0, 0);

      // 播放按钮加载完成
      buttonImg.onload = () => {
        // 计算居中坐标
        const x = (canvas.width - buttonImg.width) / 2;
        const y = (canvas.height - buttonImg.height) / 2;

        // 绘制播放按钮(带透明度)
        ctx.globalAlpha = 0.8; // 设置透明度[1](@ref)
        ctx.drawImage(buttonImg, x, y);

        // 输出合并后的图片
        resolve(canvas.toDataURL("image/png"));
      };

      buttonImg.onerror = () => reject("播放按钮加载失败");
      buttonImg.src = buttonUrl;
    };

    coverImg.onerror = () => reject("封面加载失败");
    coverImg.src = coverUrl;
  });
}

⭐效果

效果演示:https://yongma16.xyz/react-mjml
view

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!

sence

👍 点赞,是我创作的动力!

⭐️ 收藏,是我努力的方向!

✏️ 评论,是我进步的财富!

💖 最后,感谢你的阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yma16

感谢支持!共勉!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值