EG/demo/VIDEO_INTEGRATION_GUIDE.md
2025-07-02 09:49:59 +08:00

7.3 KiB

Panda3D 视频播放功能集成指南

概述

Panda3D 完全支持内嵌视频播放功能,通过 MovieTexture 类可以实现:

  • 视频文件播放 - 支持 MP4, AVI, MOV, MKV, WebM 等格式
  • 3D场景中的视频纹理 - 将视频作为材质应用到3D模型
  • 视频控制 - 播放、暂停、停止、调速、循环等
  • 程序化动画 - 创建动态纹理效果
  • 全景视频 - 360度球形视频播放
  • 广告牌视频 - 始终面向相机的视频面板

核心组件

1. MovieTexture 类

from panda3d.core import MovieTexture

# 创建视频纹理
movie_texture = MovieTexture("video_name")
success = movie_texture.read("path/to/video.mp4")

if success:
    # 播放控制
    movie_texture.play()           # 播放
    movie_texture.stop()           # 停止
    movie_texture.setTime(0)       # 设置播放位置
    movie_texture.setPlayRate(1.5) # 设置播放速度
    movie_texture.setLoop(True)    # 设置循环播放
    
    # 获取信息
    length = movie_texture.getVideoLength()
    current_time = movie_texture.getTime()
    is_playing = movie_texture.isPlaying()

2. 视频管理器 (VideoManager)

from video_integration import VideoManager

# 在 MyWorld 类中初始化
self.video_manager = VideoManager(self)

# 创建视频屏幕
screen = self.video_manager.create_video_screen(
    pos=(0, 0, 2),
    size=(4, 3),
    video_path="video.mp4",
    name="main_screen"
)

# 创建广告牌
billboard = self.video_manager.create_video_billboard(
    pos=(2, 0, 1),
    size=(2, 1.5),
    name="info_billboard"
)

# 创建全景视频
spherical = self.video_manager.create_spherical_video(
    pos=(0, 0, 0),
    radius=10,
    video_path="360_video.mp4",
    name="vr_environment"
)

错误修复说明

1. 任务管理器参数传递错误

问题: TypeError: missing 1 required positional argument: 'task'

原因: 使用 extraArgs 时参数顺序错误

修复方案:

# ❌ 错误的方式
self.taskMgr.add(self.update_texture, "task_name", extraArgs=[texture, data])

def update_texture(self, texture, data, task):  # task 参数位置错误
    pass

# ✅ 正确的方式
self.taskMgr.add(lambda task: self.update_texture(task, texture, data), "task_name")

def update_texture(self, task, texture, data):  # task 参数在前
    return task.cont

2. 模型依赖问题

问题: Couldn't load file models/sphere.egg

解决方案: 程序化生成几何体

def create_sphere_geometry(self, radius=1):
    """程序化创建球体几何"""
    sphere_root = self.render.attachNewNode("sphere")
    
    faces = [
        (Vec3(0, radius, 0), Vec3(0, 0, 0)),      # 前面
        (Vec3(0, -radius, 0), Vec3(0, 180, 0)),   # 后面
        (Vec3(radius, 0, 0), Vec3(0, 90, 0)),     # 右面
        (Vec3(-radius, 0, 0), Vec3(0, -90, 0)),   # 左面
        (Vec3(0, 0, radius), Vec3(-90, 0, 0)),    # 上面
        (Vec3(0, 0, -radius), Vec3(90, 0, 0)),    # 下面
    ]
    
    cm = CardMaker("sphere_face")
    cm.setFrame(-radius, radius, -radius, radius)
    
    for pos, hpr in faces:
        face = sphere_root.attachNewNode(cm.generate())
        face.setPos(pos)
        face.setHpr(hpr)
    
    return sphere_root

快速开始

1. 基础视频播放

from direct.showbase.ShowBase import ShowBase
from panda3d.core import MovieTexture, CardMaker

class VideoApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # 创建视频纹理
        movie_texture = MovieTexture("video")
        success = movie_texture.read("your_video.mp4")
        
        if success:
            # 创建显示面板
            cm = CardMaker("video_card")
            cm.setFrame(-2, 2, -1.5, 1.5)
            video_card = self.render.attachNewNode(cm.generate())
            video_card.setTexture(movie_texture)
            
            # 播放视频
            movie_texture.play()
            
        # 设置相机
        self.cam.setPos(0, -5, 0)

app = VideoApp()
app.run()

2. 集成到现有编辑器

# 在 MyWorld 类的 __init__ 方法中添加
from video_integration import VideoManager
self.video_manager = VideoManager(self)

# 在文件拖放处理中添加视频支持
def dropEvent(self, event):
    if event.mimeData().hasUrls():
        for url in event.mimeData().urls():
            filepath = url.toLocalFile()
            
            # 检查视频文件
            if self.world.video_manager.is_video_file(filepath):
                self.world.video_manager.create_video_screen(
                    pos=(0, 0, 2), 
                    video_path=filepath,
                    name=f"video_{len(self.world.video_manager.video_objects)}"
                )
            # 检查模型文件
            elif filepath.lower().endswith(('.egg', '.bam', '.obj', '.fbx')):
                self.world.importModel(filepath)

3. 视频控制示例

# 播放控制
video_manager.play_video("video_name")
video_manager.pause_video("video_name")
video_manager.stop_video("video_name")

# 速度控制
video_manager.set_video_speed("video_name", 1.5)  # 1.5倍速

# 获取信息
info = video_manager.get_video_info("video_name")
print(f"视频长度: {info['length']}秒")
print(f"当前时间: {info['current_time']}秒")
print(f"播放状态: {info['is_playing']}")

# 列出所有视频
videos = video_manager.list_videos()
for video in videos:
    print(f"视频: {video['name']}, 类型: {video['type']}, 播放中: {video['is_playing']}")

支持的视频格式

  • MP4 - 推荐格式,兼容性最好
  • AVI - 传统格式,支持良好
  • MOV - QuickTime 格式
  • MKV - 开源容器格式
  • WebM - 网络优化格式

性能优化建议

  1. 视频分辨率: 建议使用 1080p 或更低分辨率
  2. 编码格式: 优先使用 H.264 编码
  3. 文件大小: 控制在合理范围内避免内存问题
  4. 多视频播放: 同时播放多个视频时注意性能监控
  5. 纹理尺寸: 程序化纹理建议使用 2 的幂次方尺寸

常见问题解决

Q: 视频不播放怎么办?

A: 检查文件路径是否正确,文件格式是否支持,系统是否安装了相应的解码器。

Q: 动画纹理不更新?

A: 确认任务管理器正常运行,检查 task.cont 返回值。

Q: 全景视频显示异常?

A: 检查球体几何体的法线方向,确保使用 setTwoSided(True)

Q: 内存占用过高?

A: 减小纹理分辨率,限制同时播放的视频数量,及时移除不需要的视频对象。

测试文件

项目包含以下测试文件:

  • video_player_example.py - 完整的视频播放器演示
  • video_integration.py - 视频管理器模块
  • test_video_fix.py - 功能测试验证

运行测试:

python test_video_fix.py
python video_player_example.py

总结

Panda3D 的视频播放功能非常强大,支持多种使用场景。通过本指南提供的 VideoManager 类,可以轻松集成到现有项目中,实现丰富的多媒体体验。

主要优势:

  • 🔥 易于集成 - 几行代码即可添加视频功能
  • 🎯 功能丰富 - 支持多种视频显示模式
  • 🚀 性能优秀 - 基于 Panda3D 的高效渲染
  • 🛠️ 高度可定制 - 支持程序化动画和特效
  • 💡 实时控制 - 完整的播放控制接口