forked from Rowland/EG
249 lines
7.3 KiB
Markdown
249 lines
7.3 KiB
Markdown
# Panda3D 视频播放功能集成指南
|
|
|
|
## 概述
|
|
|
|
Panda3D 完全支持内嵌视频播放功能,通过 `MovieTexture` 类可以实现:
|
|
- ✅ **视频文件播放** - 支持 MP4, AVI, MOV, MKV, WebM 等格式
|
|
- ✅ **3D场景中的视频纹理** - 将视频作为材质应用到3D模型
|
|
- ✅ **视频控制** - 播放、暂停、停止、调速、循环等
|
|
- ✅ **程序化动画** - 创建动态纹理效果
|
|
- ✅ **全景视频** - 360度球形视频播放
|
|
- ✅ **广告牌视频** - 始终面向相机的视频面板
|
|
|
|
## 核心组件
|
|
|
|
### 1. MovieTexture 类
|
|
```python
|
|
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)
|
|
```python
|
|
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` 时参数顺序错误
|
|
|
|
**修复方案**:
|
|
```python
|
|
# ❌ 错误的方式
|
|
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`
|
|
|
|
**解决方案**: 程序化生成几何体
|
|
```python
|
|
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. 基础视频播放
|
|
```python
|
|
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. 集成到现有编辑器
|
|
```python
|
|
# 在 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. 视频控制示例
|
|
```python
|
|
# 播放控制
|
|
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` - 功能测试验证
|
|
|
|
运行测试:
|
|
```bash
|
|
python test_video_fix.py
|
|
python video_player_example.py
|
|
```
|
|
|
|
## 总结
|
|
|
|
Panda3D 的视频播放功能非常强大,支持多种使用场景。通过本指南提供的 VideoManager 类,可以轻松集成到现有项目中,实现丰富的多媒体体验。
|
|
|
|
主要优势:
|
|
- 🔥 **易于集成** - 几行代码即可添加视频功能
|
|
- 🎯 **功能丰富** - 支持多种视频显示模式
|
|
- 🚀 **性能优秀** - 基于 Panda3D 的高效渲染
|
|
- 🛠️ **高度可定制** - 支持程序化动画和特效
|
|
- 💡 **实时控制** - 完整的播放控制接口 |