如何使用多种节点使用视频节点本页总览使用视频节点 VideoNode 是 Dora SSR 引擎中的节点类,允许您在游戏场景中播放视频文件。它继承自 Sprite,这意味着您可以使用所有精灵节点可用的属性和方法,例如定位、缩放、旋转等。一旦 VideoNode 被挂载到游戏场景中,它将自动开始播放视频,并持续播放直到节点从场景中移除。 本教程将指导您如何使用 VideoNode,包括如何准备正确格式的视频文件以及如何在游戏中使用 VideoNode。 1. 视频格式要求 VideoNode 接受包含 Theora 视频流的 Ogg 容器。文件统一通过 Dora Content 读取,因此打包资源和挂载归档使用与其它资源相同的路径规则。 1.1 支持的视频格式 容器:Ogg(.ogv) 视频编码:Theora 色彩格式:支持 Theora 4:2:0、4:2:2 和 4:4:4,并在渲染前转换为 RGBA 音频:VideoNode 只渲染视频;Love Video 可另外通过 Dora SoLoud 同步音频 Source 分辨率/性能: 4K 和高码率流在纯软件解码时可能会占用大量 CPU 为了在中等性能设备上流畅播放,推荐使用 720p/1080p 和适中的码率 1.2 使用 FFmpeg 转换视频 可使用带 libtheora 编码器的 FFmpeg 生成 Ogg/Theora 文件: 将 MP4 转换为 Ogg/Theora # 基本转换ffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv# 指定分辨率和码率(推荐以获得更好的性能)ffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -s 1280x720 -r 30 -an output.ogv# 1080p 视频ffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -s 1920x1080 -r 30 -an output.ogv 参数说明: -c:v libtheora:使用 Theora 编码器 -q:v 7:设置视频质量(可按体积与画质需求调整) -pix_fmt yuv420p:设置像素格式为 YUV 4:2:0 -s 1280x720:设置分辨率(可选,根据需要调整) -r 30:设置帧率为 30 fps(可选,根据需要调整) -an:移除音频轨道 转换其他格式 # 从 AVI 转换ffmpeg -i input.avi -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv# 从 MOV 转换ffmpeg -i input.mov -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv 提示转换后请保留 .ogv 扩展名,并将文件放入项目的 Content 资源树。 2. 创建 VideoNode 实例 要创建 VideoNode,您需要提供视频文件的路径。VideoNode 构造函数接受两个参数: filename:Ogg/Theora 视频的 Content 路径(通常为 .ogv) looped:(可选)视频是否循环播放。默认为 false LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")-- 创建一个播放一次的 VideoNodelocal video = VideoNode("assets/video.ogv")-- 创建一个循环播放的 VideoNodelocal loopingVideo = VideoNode("assets/video.ogv", true)local VideoNode <const> = require("VideoNode")-- 创建一个播放一次的 VideoNodelocal video = VideoNode("assets/video.ogv")-- 创建一个循环播放的 VideoNodelocal loopingVideo = VideoNode("assets/video.ogv", true)import { VideoNode } from "Dora";// 创建一个播放一次的 VideoNodeconst video = VideoNode("assets/video.ogv");// 创建一个循环播放的 VideoNodeconst loopingVideo = VideoNode("assets/video.ogv", true);_ENV = Dora-- 创建一个播放一次的 VideoNodevideo = VideoNode "assets/video.ogv"-- 创建一个循环播放的 VideoNodeloopingVideo = VideoNode "assets/video.ogv", true 重要提示如果视频文件无法加载或格式不正确,VideoNode() 将返回 nil(在 TypeScript 中为 null)。在使用之前,请务必检查节点是否创建成功。 3. 将 VideoNode 挂载到场景 创建 VideoNode 实例后,您需要将其挂载到游戏场景中才能显示并开始播放。当 VideoNode 被挂载到场景时,它将自动开始播放视频,并持续播放直到节点从场景中移除。 LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")-- 创建一个 VideoNodelocal video = VideoNode("assets/video.ogv")if video then -- 设置位置 video.position = Vec2(400, 300) -- 挂载到场景(视频将自动开始播放) -- 只要节点在场景中,视频就会持续播放endlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")-- 创建一个 VideoNodelocal video = VideoNode("assets/video.ogv")if not video is nil then -- 设置位置 video.position = Vec2(400, 300) -- 挂载到场景(视频将自动开始播放) -- 只要节点在场景中,视频就会持续播放endimport { VideoNode, Vec2 } from "Dora";// 创建一个 VideoNodeconst video = VideoNode("assets/video.ogv");if (video) { // 设置位置 video.position = Vec2(400, 300); // 挂载到场景(视频将自动开始播放) // 只要节点在场景中,视频就会持续播放}_ENV = Dora-- 创建一个 VideoNodewith VideoNode "assets/video.ogv" -- 设置位置 .position = Vec2 400, 300 -- 挂载到场景(视频将自动开始播放) -- 只要节点在场景中,视频就会持续播放 自动播放一旦 VideoNode 被挂载到游戏场景,它将自动开始播放视频。只要节点保留在场景树中,视频就会逐帧持续播放。如果您将 looped 设置为 true,视频在播放到结尾时会自动从头开始重新播放。 4. 控制视频播放 由于 VideoNode 继承自 Sprite,您可以使用所有精灵属性和方法来控制视频显示: LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Scale <const> = require("Scale")local video = VideoNode("assets/video.ogv", true) -- 启用循环if video then -- 定位视频 video.position = Vec2(400, 300) -- 缩放视频 video.scaleX = 0.5 video.scaleY = 0.5 -- 旋转视频 video.angle = 45 -- 设置透明度 video.opacity = 0.8 -- 或使用动作来动画化 video:perform(Scale(2.0, 0.5, 1.0)) -- 在 1 秒内从 0.5 缩放到 2.0endlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Scale <const> = require("Scale")local video = VideoNode("assets/video.ogv", true) -- 启用循环if not video is nil then -- 定位视频 video.position = Vec2(400, 300) -- 缩放视频 video.scaleX = 0.5 video.scaleY = 0.5 -- 旋转视频 video.angle = 45 -- 设置透明度 video.opacity = 0.8 -- 或使用动作来动画化 video:perform(Scale(2.0, 0.5, 1.0)) -- 在 1 秒内从 0.5 缩放到 2.0endimport { VideoNode, Vec2, Scale } from "Dora";const video = VideoNode("assets/video.ogv", true); // 启用循环if (video) { // 定位视频 video.position = Vec2(400, 300); // 缩放视频 video.scaleX = 0.5; video.scaleY = 0.5; // 旋转视频 video.angle = 45; // 设置透明度 video.opacity = 0.8; // 或使用动作来动画化 video.perform(Scale(2.0, 0.5, 1.0)); // 在 1 秒内从 0.5 缩放到 2.0}_ENV = Dorawith VideoNode "assets/video.ogv", true -- 启用循环 -- 定位视频 .position = Vec2 400, 300 -- 缩放视频 .scaleX = 0.5 .scaleY = 0.5 -- 旋转视频 .angle = 45 -- 设置透明度 .opacity = 0.8 -- 或使用动作来动画化 \perform Scale 2.0, 0.5, 1.0 -- 在 1 秒内从 0.5 缩放到 2.0 5. 从场景中移除 VideoNode 要停止视频播放,只需从场景中移除 VideoNode: LuaTealTypeScriptYueScript-- 从父节点移除视频节点(停止播放)video:removeFromParent()-- 从父节点移除视频节点(停止播放)video:removeFromParent()// 从父节点移除视频节点(停止播放)video.removeFromParent();-- 从父节点移除视频节点(停止播放)video\removeFromParent() 6. 完整示例 以下是一个完整示例,演示如何创建 VideoNode、定位它并在游戏场景中处理它: LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Size <const> = require("Size")-- 创建一个循环播放的视频节点local video = VideoNode("assets/background_video.ogv", true)if video then -- 如果需要,缩放到适合屏幕 local visualSize = App.visualSize local videoSize = video.size local scaleX = visualSize.width / videoSize.width local scaleY = visualSize.height / videoSize.height local scale = math.min(scaleX, scaleY) video.scaleX = scale video.scaleY = scale -- 视频在挂载到场景时会自动开始播放 -- 只要节点在场景中,它就会持续播放并循环endlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Size <const> = require("Size")-- 创建一个循环播放的视频节点local video = VideoNode("assets/background_video.ogv", true)if not video is nil then -- 如果需要,缩放到适合屏幕 local visualSize = App.visualSize local videoSize = video.size local scaleX = visualSize.width / videoSize.width local scaleY = visualSize.height / videoSize.height local scale = math.min(scaleX, scaleY) video.scaleX = scale video.scaleY = scale -- 视频在挂载到场景时会自动开始播放 -- 只要节点在场景中,它就会持续播放并循环endimport { VideoNode, Vec2, Size, App } from "Dora";// 创建一个循环播放的视频节点const video = VideoNode("assets/background_video.ogv", true);if (video) { // 如果需要,缩放到适合屏幕 const visualSize = App.visualSize; const videoSize = video.size; const scaleX = visualSize.width / videoSize.width; const scaleY = visualSize.height / videoSize.height; const scale = Math.min(scaleX, scaleY); video.scaleX = scale; video.scaleY = scale; // 视频在挂载到场景时会自动开始播放 // 只要节点在场景中,它就会持续播放并循环}_ENV = Dora-- 创建一个循环播放的视频节点with VideoNode "assets/background_video.ogv", true -- 如果需要,缩放到适合屏幕 visualSize = App.visualSize videoSize = .size scaleX = visualSize.width / videoSize.width scaleY = visualSize.height / videoSize.height scale = math.min scaleX, scaleY .scaleX = scale .scaleY = scale -- 视频在挂载到场景时会自动开始播放 -- 只要节点在场景中,它就会持续播放并循环 7. 性能考虑 使用 VideoNode 时,请注意以下性能提示: 分辨率:为目标设备使用适当的分辨率(720p 或 1080p)。更高的分辨率需要更多的 CPU 资源进行解码。 码率:适中的码率可以在质量和性能之间取得良好的平衡。非常高的码率可能导致低端设备出现卡顿。 帧率:推荐使用恒定帧率(CFR)。可变帧率可能导致时序问题。 多个视频:同时播放多个视频可能会占用大量 CPU。考虑限制并发 VideoNode 的数量。 后台处理:VideoNode 使用后台线程进行解码,这有助于保持流畅的游戏体验,但仍需要 CPU 资源。 8. 总结 在本教程中,您学习了如何: 使用 FFmpeg 将视频文件准备为正确的 Ogg/Theora 格式 创建 VideoNode 实例 将 VideoNode 挂载到游戏场景(会自动开始播放) 使用 Sprite 属性控制视频显示 处理视频循环 请记住,VideoNode 在挂载到场景时会自动开始播放,只要它保留在场景树中就会持续播放。这使得它非常适合背景视频、过场动画或任何需要在游戏中连续播放视频的场景。 有关 VideoNode 的更多信息,请参阅 VideoNode API 文档。