当前位置: 首页 > news >正文

集团网站推广凡科网站可以做seo优化

集团网站推广,凡科网站可以做seo优化,设计师学编程能自己做网站吗,开发公司替业主承担物业费承诺书在部分浏览器环境或业务场景下&#xff0c;直接使用 <video> 标签加载视频会出现首帧延迟的情况。以下方法通过 WebGPU Canvas 2D 将视频帧绘制到自定义 Canvas 上&#xff0c;让 <video> 只做解码&#xff0c;WebGPU 接管渲染&#xff0c;通过最小化对象创建 精…

在部分浏览器环境或业务场景下,直接使用 <video> 标签加载视频会出现首帧延迟的情况。

以下方法通过 WebGPU + Canvas 2D 将视频帧绘制到自定义 Canvas 上,让 <video> 只做解码,WebGPU 接管渲染,通过最小化对象创建 + 精准帧回调,实现高性能、可扩展、跨端一致的视频播放管线。

HTML 部分

<video id="instructional_video_id_2" :src="instru_video_src" autoplay loop muted playsinlinestyle="display: none;"></video>
<canvas id="instructional_video_id_1" width="640" height="360"style="width: 32.3125rem; height: 18.25rem;"></canvas>

JS 代码

import {WebGLVideoRenderer} from './video-canvas.js';const appInstance = createApp({data() {return {videoElement: null,isVideoLoading: false,lastVideoUrl: null,isRendering: false,renderer: null,}},mounted() {this.initRender()},methods: {initRender() {const canvas = document.getElementById('instructional_video_id_1');this.renderer = new WebGLVideoRenderer(canvas);this.videoElement = document.getElementById('instructional_video_id_2');if (!this.isVideoLoading) {this.isVideoLoading = truethis.videoElement.addEventListener('play', () => {// 视频播放时开始绘制到 canvasthis.drawVideoFrame();});this.videoElement.addEventListener('pause', () => {this.stopRendering();});this.videoElement.addEventListener('ended', () => {this.stopRendering();// 视频播放结束时重新播放// this.videoElement.currentTime = 0;// this.videoElement.play();});this.videoElement.addEventListener('error', () => {console.error('视频加载失败');});}},// 初始化视频initVideo(src) {if (this.lastVideoUrl === src) {return}this.lastVideoUrl = srcif (src === null) {return}// 设置视频源this.setVideoSource(src);},// 渲染单帧renderFrame() {// 直接调用 WebGL 渲染器this.renderer.render(this.videoElement);},// 绘制视频帧到 canvasdrawVideoFrame() {if (this.isRendering) return;this.isRendering = true;const useRVFC = 'requestVideoFrameCallback' in this.videoElement;if (useRVFC) {const rvfcLoop = () => {if (!this.isRendering) return;this.renderFrame();this.videoElement.requestVideoFrameCallback(rvfcLoop);};this.videoElement.requestVideoFrameCallback(rvfcLoop);} else {const renderLoop = () => {if (!this.isRendering) return;if (this.videoElement && !this.videoElement.paused && !this.videoElement.ended) {this.renderFrame()}requestAnimationFrame(renderLoop);};requestAnimationFrame(renderLoop);}},// 停止渲染stopRendering() {this.isRendering = false;},// 设置视频源setVideoSource(src) {this.videoElement.src = src;this.videoElement.load();// this.videoElement.play();},}

video-canvas.js代码

// video-canvas.js
export class WebGLVideoRenderer {constructor(canvas) {this.canvas = canvas;this.device = null;this.pipeline = null;this.sampler = null;this.bindGroupLayout = null;this.context = null;// 新增:可复用的对象this.currentExternalTexture = null;this.currentBindGroup = null;this.renderPassDescriptor = null;this.init();}async init() {if (!navigator.gpu) throw new Error('WebGPU not supported');const adapter = await navigator.gpu.requestAdapter({ powerPreference: 'high-performance' });this.device = await adapter.requestDevice();this.context = this.canvas.getContext('webgpu');const format = navigator.gpu.getPreferredCanvasFormat();this.context.configure({device: this.device,format,alphaMode: 'opaque'});// 着色器不变const code = `@vertex fn vs(@builtin(vertex_index) i: u32) ->@builtin(position) vec4f {const pos = array(vec2f(-1, -3), vec2f(3, 1), vec2f(-1, 1));return vec4f(pos[i], 0, 1);}@group(0) @binding(0) var s: sampler;@group(0) @binding(1) var t: texture_external;@fragment fn fs(@builtin(position) p: vec4f) ->@location(0) vec4f {let uv = p.xy / vec2f(textureDimensions(t));return textureSampleBaseClampToEdge(t, s, uv);}`;const shader = this.device.createShaderModule({ code });this.bindGroupLayout = this.device.createBindGroupLayout({entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },{ binding: 1, visibility: GPUShaderStage.FRAGMENT, externalTexture: {} }]});this.pipeline = this.device.createRenderPipeline({layout: this.device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] }),vertex: { module: shader, entryPoint: 'vs' },fragment: { module: shader, entryPoint: 'fs', targets: [{ format }] },primitive: { topology: 'triangle-list' }});this.sampler = this.device.createSampler({magFilter: 'linear', minFilter: 'linear'});// RenderPassDescriptor 的骨架,view 每帧再填this.renderPassDescriptor = {colorAttachments: [{view: undefined,            // 占位,下面会替换loadOp: 'clear',storeOp: 'store'}]};}render(video) {if (!this.device) return;// 1. 画布尺寸变化时再改const { videoWidth, videoHeight } = video;if (this.canvas.width !== videoWidth || this.canvas.height !== videoHeight) {this.canvas.width  = videoWidth;this.canvas.height = videoHeight;}// 2. 只有在必要时才重新生成 BindGroup//    importExternalTexture 每次都会返回新对象,必须每帧调用const externalTexture = this.device.importExternalTexture({ source: video });if (this.currentExternalTexture !== externalTexture) {this.currentExternalTexture = externalTexture;this.currentBindGroup = this.device.createBindGroup({layout: this.bindGroupLayout,entries: [{ binding: 0, resource: this.sampler },{ binding: 1, resource: externalTexture }]});}// 3. 更新 colorAttachment.viewthis.renderPassDescriptor.colorAttachments[0].view =this.context.getCurrentTexture().createView();// 4. 复用 RenderPassDescriptor,不再每帧 newconst encoder = this.device.createCommandEncoder();const pass = encoder.beginRenderPass(this.renderPassDescriptor);pass.setPipeline(this.pipeline);pass.setBindGroup(0, this.currentBindGroup);pass.draw(3);pass.end();this.device.queue.submit([encoder.finish()]);}dispose() {this.device?.destroy();}
}

关键点

  • <video> 元素仅作解码器,不可见 (display: none)。

  • 每帧通过 requestVideoFrameCallback(优先)或 requestAnimationFrame 轮询,把最新纹理塞进 WebGPU。

  • Canvas 尺寸动态跟随 video.videoWidth / videoHeight,防止花屏。

http://www.dtcms.com/a/450351.html

相关文章:

  • 中国小康建设网官方网站化妆品备案
  • 曲靖住房和城乡建设局网站做网站电话
  • 【笔记】2.1.1.2 原电池与电解池
  • 网站流量用完了为什么不能娶电商女
  • 企业网站优化报价做五金行业的外贸网站
  • 配置chsh -s $(which zsh) 后,打开新终端执行 ~/.bashrc 还是 ~/.zshrc ?
  • Tmux 入门 + 常用命令 (解决 ssh 远程终端断连 - 实现 Linux终端多任务 + 多窗口)
  • 网站建站好处中企动力网站
  • 浙江2025年高考录取政策变化
  • 【C++实战(76)】从0到1:C++在MQTT物联网开发中的实战之旅
  • VGG改进(13):基于FFT的Frequency Attention模块应用
  • 商业网站教程阿里云有主体新增网站
  • 《数据密集型应用系统设计2》--数据系统对比:OLAP/OLTP,数仓/数据湖/数据湖屋
  • Oracle OCP认证考试题目详解082系列第55题
  • 学做宝宝衣服网站好h5和小程序有什么区别
  • day5
  • 2025-10-06 Python不基础13——mro
  • 那片海dede织梦源码企业网络公司工作室网站模板源码模板php网页游戏维京传奇
  • 【深度学习03】神经网络基本骨架、卷积、池化、非线性激活、线性层、搭建网络
  • 新媒体营销seo个人优化方案案例
  • Redis项目应用总结(苍穹外卖/黑马头条/乐尚代驾)
  • 做网站js还是jq2021年世界500强榜单
  • 建设旅游网站的费用预算杭州抖音代运营
  • 【LaTeX】 13 LaTeX 长文档结构管理
  • Python入门:Python3基础练习题详解
  • 高端网站建设加盟帮人做彩票网站
  • 哪个网站做的ppt模板好查查企业网
  • 为什么做的网站别的浏览器打不开怎么回事做网站规划
  • 做影视后期应该关注哪些网站做神马网站优化快速
  • 测试题——1