7.Unity进阶视频播放总结

7.总结


7.1 知识点

学习的主要内容

总结讲什么

兼容性问题

播放需求


7.2 核心要点速览

视频文件基础

视频文件的本质:视频文件 = 容器格式 + 编解码器。容器(如 .mp4、.avi、.mov)只是”包装盒”,真正决定能否播放的是内部的编解码器。

概念 说明
容器格式 文件扩展名,如 MP4、AVI、MOV、WebM,只决定”怎么打包”
编解码器 压缩/解压视频数据的算法,如 H.264、H.265、VP8,决定”能否播放”
编码器 将原始视频数据压缩成特定格式
解码器 将压缩的视频数据解压还原播放

硬件解码 vs 软件解码

类型 原理 优点 缺点
硬件解码 由 GPU 或专用芯片处理 性能高、功耗低、不占用 CPU 兼容性受限,部分格式不支持
软件解码 由 CPU 处理 兼容性好,支持更多格式 占用 CPU 资源,功耗较高

选择建议:优先使用硬件解码支持的格式(如 H.264),性能更好;跨平台需求强时考虑 VP8。

Unity 视频兼容性

编辑器与目标平台的差异:Unity 编辑器使用的视频解码能力取决于电脑系统,但发布到不同平台时,目标设备的解码能力可能完全不同。常见问题:在编辑器能播放的视频,打包后某平台无法播放。

各平台编解码器支持

编解码器 特点 平台支持
H.264 硬件加速支持最广,性能最优 Windows、macOS、iOS、Android(推荐首选)
H.265 压缩率更高,但硬件支持较少 部分新设备支持
VP8 跨平台兼容性好,软件解码为主 大多数平台支持,Android 可有硬件辅助

一劳永逸方案:MP4 容器 + H.264 编解码器,根据设备情况考虑 VP8 和 H.265。

视频剪辑设置

以下是视频剪辑设置的相关知识整理为表格形式:

类别 参数 介绍
设置参数 sRGB 是否开启 sRGB,sRGB 是通用色彩标准,避免不同设备出现色差,一般默认勾选
Transcode 是否开启转码,开启后下方参数才能设置
Dimensions 控制源文件内容大小调整方式:
1. Original:保持原始大小
2. Three Quarter Res:调整为原始宽高的四分之三
3. Half Res:调整为原始宽高的一半
4. Quarter Res:调整为原始宽高的四分之一
5. Square(1024x1024):调整为 1024x1024 正方形图像,宽高比可控
6. Square(512x512):调整为 512x512 正方形图像,宽高比可控
7. Square(256x256):调整为 256x256 正方形图像,宽高比可控
8. Custom:调整为自定义分辨率,宽高比可控,可设置Width(生成图像的宽)、Height(生成图像的高)
9. Aspect Ratio:调整图像大小时的宽高比,有No Scaling(添加黑色区域保留原始宽高比)、Stretch(拉伸原始内容填充目标分辨率)
Codec 选择用于转码的解编码器:
1. Auto:为目标平台选择最合适的视频编解码器
2. H264:MPEG–4 高级视频编码 (AVC) 视频编解码器,受大多数平台硬件支持
3. H265:MPEG-H Part 2 或高效视频编码 (HEVC) 视频编解码器,受某些平台硬件支持
4. VP8:VP8 视频编解码器,受大多数平台软件支持,部分平台(如 Android 和 WebGL)硬件支持
Bitrate Mode 相对于所选编解码器的基线配置文件的低、中或高比特率
Spatial Quality 决定视频图像在转码过程中是否压缩大小:
1. Low Spatial Quality:转码时图像大小显著减小(通常为原始尺寸的四分之一),播放时扩展回原始大小,节省存储空间但播放时模糊度最大
2. Medium Spatial Quality:转码时图像大小适度减小(通常为原始尺寸的一半),播放时扩展回原始大小,图像更清晰,存储空间有所减少
3. High Spatial Quality:不调整大小,保持视频原始视觉清晰度
Keep Alpha 保留 Alpha 透明通道并在转码期间将其编码,仅对具有 Alpha 通道的源显示,Android 平台原生 VP8 不支持透明度,需启用转码
Deinterlace(去交错设置) 控制隔行扫描源在转码期间如何解除隔行扫描,优化动态画面清晰度:
1. Off:源文件没有隔行扫描,不进行隔行扫描
2. Even:采用每个帧的偶数行,插入创建缺失内容,丢弃奇数行
3. Odd:采用每个帧的奇数行,插入创建缺失内容,丢弃偶数行
隔行扫描和逐行扫描区别
隔行扫描:每一帧被分割为两场,包含奇数或偶数扫描行,交替显示,存在闪烁,人眼易疲劳
逐行扫描:每次显示整个扫描帧,画面更平滑,闪烁较小
Flip Horizontally 选中时,转码时将视频源文件内容沿垂直轴翻转实现左右翻转
Flip Vertically 选中时,转码时将视频源文件内容沿水平轴翻转实现上下翻转
Import Audio 只有存在音频轨道的视频才会出现该选项,勾选时,转码期间会导入音频轨道

VideoPlay视频播放器

VideoPlayer组件参数

参数分类 参数名称 参数说明
视频源设置 Source 视频源类型,有 Video Clip 和 URL 两种选择
Video Clip 可直接将视频剪辑拖入或选择视频剪辑进行关联
URL 选择视频的路径,可以是远程视频路径,可点击 Browse 选择,也能通过代码关联
播放控制 Play On Awake 场景启动时自动播放视频,若想自行控制播放时机则取消勾选
Wait For First Frame 勾选后,Unity 等待视频第一帧准备好显示;取消勾选可能丢弃前几帧以同步游戏时间
Loop 设置视频是否循环播放
Skip On Drop 决定是否允许视频播放器跳过帧以赶上当前时间
Playback Speed 播放速度的乘数,取值范围 0 - 10,1 为正常速度,2 表示两倍速播放
渲染方式 Render Mode 包括 Camera Far Plane、Camera Near Plane、Render Texture、Material Override、API Only 等多种渲染模式:
- Camera Far Plane:在摄像机的远平面上渲染视频,Camera 定义接受视频的摄像机,Alpha 可设置视频的全局透明度,3D Layout 包含不同的 3D 布局渲染方式
- Camera Near Plane:在摄像机的近平面上渲染视频
- Render Texture:将视频渲染到渲染纹理中,Target Texture 用于指定渲染图像的渲染纹理,分辨率最好和视频一致,可通过 UI 创建 image 关联视频纹理
- Material Override:通过游戏对象渲染器的材质将视频渲染到游戏对象的选定纹理属性中,Renderer 用于指定渲染图像的渲染器,若为 None 则使用 Video Player 依附对象的渲染器
- API Only:不预先设置渲染位置,通过代码使用 Video Player 中的 texture 属性设置视频渲染位置
宽高比设置 Aspect Ratio 有 No Scaling、Fit Vertically、Fit Horizontally、Fit Inside、Fit Outside、Stretch 等多种宽高比设置方式:
- No Scaling:不使用缩放
- Fit Vertically:垂直适应目标矩形,必要时裁剪左右或留黑边保留原宽高比
- Fit Horizontally:水平适应目标矩形,必要时裁剪上下或留黑边保留原宽高比
- Fit Inside:对原视频缩放不裁剪,但可能留黑边
- Fit Outside:对原视频缩放,可能裁剪但不留黑边
- Stretch:水平和垂直方向均缩放以适应目标矩形,不保留源宽高比
音频输出设置 Audio Output Mode 包括 None、Audio Source、Direct、API Only 等音频输出模式:
- None:不播放音频
- Audio Source:将音频发送给指定的音频源对象,允许 Unity 的音频处理,关联音频源后可通过其控制视频声音
- Direct:直接绕过 Unity 音频处理,发送给音频输出硬件输出,如手机硬件
- API Only:通过代码将音频样本发送到关联的 AudioSampleProvider 监听器
Mute 设置静音
Volume 调节音量
Track Enabled 启用关联的音频轨道用于播放,必须在播放前设置,如“Track 0[en, 2 ch]”表示双声道音频轨道

VideoPlayer参数和方法

参数设置

// 是否自动播放,设置为 false 表示不自动播放
videoPlayer.playOnAwake = false; 
// 设置渲染模式为在摄像机的远平面上渲染
videoPlayer.renderMode = VideoRenderMode.CameraFarPlane; 
// 设置目标渲染贴图为 renderTexture(需提前定义)
videoPlayer.targetTexture = renderTexture; 
// 设置目标摄像机为名为 "Main Camera" 的摄像机
videoPlayer.targetCamera = GameObject.Find("Main Camera"); 
// 设置目标摄像机的透明度为 0.5
videoPlayer.targetCameraAlpha = 0.5f; 
// 以 Over-Under3D 格式呈现视频
videoPlayer.targetCamera3DLayout = Video3DLayout.OverUnder3D; 
// 设置视频源模式为使用视频剪辑
videoPlayer.source = VideoSource.VideoClip; 
videoPlayer.clip = videoClip; 
// 或者设置视频源模式为使用 URL 路径
// videoPlayer.source = VideoSource.Url; 
// videoPlayer.url = Application.streamingAssetsPath + "/Video.mp4"; 
// 设置视频不循环播放
videoPlayer.isLooping = false; 

视频状态输出

// 输出视频总时长,单位为秒
print(videoPlayer.length); 
// 输出当前视频播放的时长,单位为秒
print(videoPlayer.time); 
// 输出视频的总帧数
print(videoPlayer.frameCount); 
// 输出当前视频播放到的帧
print(videoPlayer.frame); 

方法

// 播放视频
videoPlayer.Play(); 
// 停止视频,再次播放时会从头开始
videoPlayer.Stop(); 
// 暂停视频播放
videoPlayer.Pause(); 
// 为视频准备数据,提前调用可避免播放时卡顿
videoPlayer.Prepare(); 

事件

// 准备完成事件,当视频准备完成后触发,可用于避免播放卡顿
videoPlayer.prepareCompleted += (v) =>
{
    print("准备完成");
    isPrepareCompleted = true;
};
// 开始事件,当执行 videoPlayer.Play() 方法后调用
videoPlayer.started += (v) =>
{
    print("当执行 player 播放方法后 会调用的事件");
};
// 结尾事件,当视频播放到结尾处时调用
videoPlayer.loopPointReached += (v) =>
{
    print("视频播放到结尾处时会调用的事件");
};

全景视频

Unity 支持两种类型的全景视频:

  • 等距圆柱投影布局:也被称为球面投影、简化圆柱投影、矩形投影或普通圆柱投影。这种布局的全景视频,其宽高比通常为 2:1(对应 360 度内容)或 1:1(对应 180 度内容)。
  • 立方体贴图布局:由六个正方形纹理的集合构成。该布局的全景视频宽高比包括 1:6、3:4、4:3、6:1 等。可以通过视频分辨率的比值来判断该全景视频属于哪种布局类型。

在 Unity 中使用全景视频

  1. 导入等距圆柱投影布局的视频文件时,可以通过观察其分辨率是否为 2:1 来进行初步判定。
  2. 使用 Video Player 组件,将其渲染模式设置为以 Render Texture(渲染纹理)来播放视频。
  3. 设置接受渲染纹理的天空盒材质,具体操作为将天空盒材质的着色器设置为 Skybox>Panoramic。
  4. 配置场景,使其使用所设置的天空盒材质。
  5. 运行测试,尝试旋转摄像机的角度,查看全景视频的播放效果。

注意:为了获得更好的视觉效果,尽量使用较高分辨率的全景视频,如 4K 或 8K 分辨率。但对于一些老旧设备或者移动设备,由于性能限制,可能最多只能支持 2K 分辨率,具体情况需根据实际设备性能来确定。

使用全景视频时的注意事项

  1. Render Texture(渲染纹理)

    • 确保 Render Texture 的 Size(尺寸)与视频的尺寸保持一致,可以在视频预览窗口中选择 Source Info(源信息)来查看视频的分辨率。
    • 将渲染纹理的 Depth Buffer(深度缓冲区)设置为 No depth buffer(无深度缓冲区)。
  2. 天空盒材质

    • 对于等距圆柱投影布局,在天空盒材质中将 Mapping(映射)设置为 Latitude Longitude Layout(经纬度布局),然后根据视频是 180 视图还是 360 视图,相应地选择 360 degree(360 度)或者 180 degree(180 度)。
    • 对于立方体贴图布局,将 Mapping 设置为 6 Frames Layout(6 帧布局)。
    • 如果视频是 VR 视频:
      • 当视频内容分为左右双眼显示时,需要将天空盒材质的 3D Layout(3D 布局)设置为 Side by Side(并排)。
      • 当左右侧内容在视频中呈上下分布时,3D Layout 应设置为 Over Under(上下)。

7.3 面试题精选

基础题

1. 视频文件格式和编解码器有什么区别?

题目

请解释视频文件的容器格式和编解码器的区别,为什么同一个 MP4 文件在不同设备上可能无法播放?

深入解析

视频文件由两部分组成:容器格式和编解码器。容器格式(如 MP4、AVI、MOV)只是”包装盒”,决定文件的扩展名和内部数据组织方式;编解码器(如 H.264、H.265、VP8)才是真正压缩和解压视频数据的算法。

同一个 MP4 文件在不同设备上可能无法播放,原因在于:

  • 编解码器不兼容:设备缺少对应的解码器,无法解压视频数据
  • 硬件解码限制:某些格式需要硬件支持,老旧设备 GPU 不支持新编解码器
  • 平台差异:iOS、Android、Windows 支持的编解码器不完全相同

开发建议:优先使用 H.264 编解码器 + MP4 容器,硬件支持最广;跨平台项目可考虑 VP8。

答题示例

视频文件由容器格式和编解码器两部分组成。容器格式决定文件扩展名和数据组织方式,编解码器负责压缩和解压视频数据。

同一个 MP4 文件在不同设备无法播放,通常是因为目标设备缺少对应的解码器或硬件不支持。开发中建议优先使用 H.264 编解码器,它的硬件加速支持最广。

参考文章
  • 2.视频格式和编解码器
  • 3.Unity中的视频兼容性

2. VideoPlayer 组件有哪些渲染模式?各适用什么场景?

题目

Unity 的 VideoPlayer 组件支持哪些渲染模式?请简述每种模式的适用场景。

深入解析

VideoPlayer 支持 5 种渲染模式:

渲染模式 说明 适用场景
Camera Far Plane 在摄像机远平面渲染 全屏背景视频、过场动画
Camera Near Plane 在摄像机近平面渲染 视频覆盖在场景前方
Render Texture 渲染到纹理 UI 上播放视频、RawImage 显示
Material Override 渲染到物体材质 电视屏幕、广告牌等 3D 物体播放视频
API Only 通过代码控制纹理 自定义渲染逻辑、动态分配

最常用的是 Render Texture 模式,配合 UGUI 的 RawImage 显示视频;Material Override 适合在 3D 物体表面播放视频。

答题示例

VideoPlayer 有五种渲染模式:Camera Far/Near Plane 适合全屏视频,Render Texture 配合 UI 使用最灵活,Material Override 用于 3D 物体表面播放视频,API Only 用于自定义渲染逻辑。

实际开发中 Render Texture 模式最常用,可以配合 RawImage 在 UI 上显示视频内容。

参考文章
  • 5.VideoPlayer视频播放器

进阶题

1. 如何解决视频在编辑器能播放但打包后无法播放的问题?

题目

在 Unity 编辑器中视频播放正常,但打包发布到 Android 或 iOS 后视频无法播放,可能的原因有哪些?如何解决?

深入解析

这是典型的平台兼容性问题,原因和解决方案:

原因分析

  1. 编解码器不支持:目标平台硬件不支持视频使用的编解码器
  2. 转码未开启:视频未针对目标平台转码,使用了平台不支持的格式
  3. 视频资源未正确打包:StreamingAssets 路径问题或资源未包含在构建中

解决方案

  1. 开启转码:选中视频剪辑,启用 Transcode,选择目标平台支持的编解码器(推荐 H.264)
  2. 使用 URL 模式:将视频放在 StreamingAssets 目录,通过 URL 加载
  3. 平台测试:在 Video Clip 的 Inspector 中查看 Source Info,确认转码后的编解码器

最佳实践

  • 使用 MP4 + H.264 组合,兼容性最好
  • 移动端注意分辨率,过高可能导致解码卡顿
  • 发布前在目标平台真机测试
答题示例

这个问题通常是平台编解码器兼容性导致的。Unity 编辑器使用电脑系统的解码能力,但目标平台可能不支持相同的编解码器。

解决方案:在视频剪辑设置中开启 Transcode 转码,选择 H.264 编解码器,它的硬件支持最广。同时建议使用 MP4 容器格式,并在目标平台真机测试。

参考文章
  • 3.Unity中的视频兼容性
  • 4.视频剪辑设置相关

2. 如何避免视频播放开始时的卡顿?

题目

视频播放开始时经常出现短暂卡顿,如何优化?

深入解析

视频播放卡顿的原因是数据加载和解码需要时间。解决方案:

使用 Prepare 方法预加载

videoPlayer.playOnAwake = false;
videoPlayer.Prepare();

videoPlayer.prepareCompleted += (v) =>
{
    // 准备完成后再播放,避免卡顿
    videoPlayer.Play();
};

关键流程

  1. 关闭 playOnAwake,手动控制播放时机
  2. 调用 Prepare() 提前加载视频数据
  3. 监听 prepareCompleted 事件,准备完成后再 Play()

其他优化建议

  • 视频文件不要过大,移动端建议控制在 1080p 以内
  • 使用硬件解码支持的编解码器(H.264)
  • 对于短视频,可考虑预加载到内存
答题示例

视频播放卡顿是因为数据加载和解码需要时间。解决方案是使用 Prepare 方法预加载:先关闭 playOnAwake,调用 Prepare 预加载视频数据,监听 prepareCompleted 事件,准备完成后再调用 Play 播放。

这样视频数据已经加载到内存,播放时就不会卡顿了。

参考文章
  • 5.VideoPlayer视频播放器

深度题

1. 设计一个完整的视频播放系统,支持进度条控制、暂停、倍速播放

题目

请设计一个 Unity 视频播放系统,要求支持:进度条拖动控制播放位置、暂停/继续、倍速播放(0.5x/1x/1.5x/2x)。请给出核心实现思路和关键代码。

深入解析

系统设计思路

  1. UI 结构:RawImage(显示视频)+ Slider(进度条)+ Button(暂停/播放)+ Dropdown(倍速选择)
  2. 核心组件:VideoPlayer + Render Texture
  3. 关键逻辑
    • 进度条拖动:Slider 值变化时设置 videoPlayer.time
    • 进度条更新:Update 中根据 videoPlayer.time / videoPlayer.length 更新 Slider
    • 倍速播放:设置 videoPlayer.playbackSpeed
    • 状态同步:注意拖动时暂停更新,避免冲突

核心代码

public class VideoPlayerController : MonoBehaviour
{
    public VideoPlayer videoPlayer;
    public Slider progressSlider;
    public Button playPauseBtn;
    public TMP_Dropdown speedDropdown;

    private bool isDragging = false;

    void Start()
    {
        videoPlayer.playOnAwake = false;
        videoPlayer.Prepare();
        
        videoPlayer.prepareCompleted += (v) =>
        {
            videoPlayer.Play();
        };

        progressSlider.onValueChanged.AddListener(OnSliderChanged);
        speedDropdown.onValueChanged.AddListener(OnSpeedChanged);
        playPauseBtn.onClick.AddListener(OnPlayPauseClick);
    }

    void Update()
    {
        if (!isDragging && videoPlayer.isPlaying)
        {
            progressSlider.value = (float)(videoPlayer.time / videoPlayer.length);
        }
    }

    void OnSliderChanged(float value)
    {
        if (isDragging)
        {
            videoPlayer.time = videoPlayer.length * value;
        }
    }

    void OnSpeedChanged(int index)
    {
        float[] speeds = { 0.5f, 1f, 1.5f, 2f };
        videoPlayer.playbackSpeed = speeds[index];
    }

    void OnPlayPauseClick()
    {
        if (videoPlayer.isPlaying)
            videoPlayer.Pause();
        else
            videoPlayer.Play();
    }

    public void OnDragStart() => isDragging = true;
    public void OnDragEnd() => isDragging = false;
}

注意事项

  • 拖动进度条时需要暂停自动更新,否则会冲突
  • Slider 需要添加 EventTrigger 监听拖动开始/结束事件
  • 倍速播放范围 0~10,但过高可能导致卡顿
答题示例

核心思路是分离”用户拖动”和”自动更新”两种状态。进度条拖动时设置 isDragging 标志,暂停自动更新,用户释放后再恢复。

关键点:使用 Prepare 预加载避免卡顿,Slider 的 onValueChanged 控制播放位置,playbackSpeed 控制倍速,isPlaying 判断播放状态来切换暂停/播放。

参考文章
  • 5.VideoPlayer视频播放器

2. 如何在 Unity 中实现全景视频播放?有哪些关键技术点?

题目

请说明在 Unity 中实现全景视频播放的完整流程,以及需要特别注意的技术细节。

深入解析

全景视频类型判断

  • 等距圆柱投影:宽高比 2:1(360°)或 1:1(180°)
  • 立方体贴图:宽高比 1:6、3:4、4:3、6:1

实现流程

  1. 创建 Render Texture

    • Size 与视频分辨率一致
    • Depth Buffer 设为 No depth buffer
  2. 配置 VideoPlayer

    • Render Mode 设为 Render Texture
    • 关联创建的 Render Texture
  3. 创建天空盒材质

    • Shader 选择 Skybox > Panoramic
    • 等距圆柱投影:Mapping 设为 Latitude Longitude Layout
    • 立方体贴图:Mapping 设为 6 Frames Layout
  4. 设置场景天空盒:Window > Rendering > Lighting,关联天空盒材质

  5. VR 视频额外设置

    • 左右并排:3D Layout 设为 Side by Side
    • 上下分布:3D Layout 设为 Over Under

性能优化

  • 尽量使用高分辨率(4K/8K),但移动端可能限制在 2K
  • 全景视频解码压力大,注意目标设备性能

应用场景:VR 项目、动态天空盒、沉浸式过场动画

答题示例

全景视频实现分三步:首先创建与视频分辨率一致的 Render Texture,Depth Buffer 设为无;然后 VideoPlayer 以 Render Texture 模式渲染;最后创建 Skybox/Panoramic 材质,根据视频类型设置 Mapping,并关联到场景天空盒。

关键点:Render Texture 尺寸必须匹配视频,等距圆柱投影用 Latitude Longitude Layout,VR 视频需额外设置 3D Layout。

参考文章
  • 6.全景视频


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏