Skip to content

Commit

Permalink
feat: 新增PlayController 以优化运镜逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
solome committed Mar 7, 2022
1 parent 18077fe commit a8d5951
Show file tree
Hide file tree
Showing 66 changed files with 3,079 additions and 293 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,33 @@ const vreoplayer = new Player(five, {

这样,在微信浏览器或微信小程序 `WebView` 中也能正常使用自动播效果。

### 性能优化

提高播放性能目前有两个策略:降低贴图分辨率和提前预载。

#### 降低图片分辨率

可以设置 `five.imageOptions.size` 来降低渲染引擎的贴图尺寸,这样下载速度会变快且内存占用也会降低。
你也可以配置 **Vreo** 参数来达到类似的效果:

```ts
const vreoplayer = new Player(five, { imageOptions: { size: 1024 } })
```

#### 自动预载

如果网络不稳定,可以提前预载静态资源,这样播放过程中不会卡顿:

```ts
// 全局预载
const vreoplayer = new Player(five, { autoPreload: true })

// 针对某一份剧本数据预载
vreoplayer.load(vreoUnit, 0, true)

```


## API 文档

详细的 API 文档请参考:[Vreo API](https://realsee-developer.github.io/vreo/index.html)
2 changes: 1 addition & 1 deletion __test__/AppReact.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react'
import { useVreoAction, useVreoPausedState } from '../resources/react'
import { VreoUnit } from '../typedoc/Player'
import { vreoUnitD as data } from './data/vreo-units/vreo-unit-d-new'
import { vreoUnit as data } from './data/vreo-units/vreo-unit-work3'

export function App() {
const loaded = React.useRef(false)
Expand Down
173 changes: 173 additions & 0 deletions __test__/PlayController/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { unsafe__useFiveInstance } from '@realsee/five/react'
import * as React from 'react'
import { PlayController } from '../../resources/PlayController'
import { VreoKeyframe, VreoKeyframeEnum, VreoUnit } from '../../resources/typings/VreoUnit'

import './index.css'

// 全局单例:可以放置在您的 Store/Controller 层里面。
const playController = new PlayController()

Object.assign(window, { $playController: playController })

/**
* 触发按钮
*/
function Button() {
const [state, setState] = React.useState(false)

React.useEffect(() => {
const setPlaying = () => setState(true)
const setPaused = () => setState(false)
playController.on('playing', setPlaying)
playController.on('paused', setPaused)

return () => {
playController.off('playing', setPlaying)
playController.off('paused', setPaused)
}
}, [])

return (
<button
className="pure-button pure-button-primary PlayController-Button"
onClick={async () => {
if (!playController.paused) {
await playController.pause()
return
}

if (playController.vreoUnit) {
await playController.play()
return
}

// 构造讲房数据
const vreoUnit: VreoUnit = {
categoryId: 'agent_navigation',
categoryText: '经纪人讲房',
frontRequestId: '10010',
index: 0,
video: {
url: '//vrlab-public.ljcdn.com/release/vradmin/media/047b652f-bc01-487a-231e-2549595b5a85.mp3',
start: 0,
end: 130724,
duration: 130724,
},
keyframes: []
}
// 请求讲房序列帧
const json = await fetch('//vrlab-public.ljcdn.com/release/vradmin/media/f8e6ebf8-ad0b-41e2-16b2-6ded49cda037.json')
const tracks = (await json.json()).track

const keyframes = tracks.map((track: Record<string, any>) => {
const vreoKeyframe: VreoKeyframe = {
uuid: '',
// 由于是人为录制的,所以所有的序列帧都是 Custom 类型
type: VreoKeyframeEnum.Custom,
start: track.currentTime,
end: 0,
data: Object.assign({
// 可以以字段内内容 识别是 经纪人讲房录制的数据
type: 'AgentNavigation',
}, track)
}
return vreoKeyframe
})

vreoUnit.keyframes = keyframes

await playController.load(vreoUnit)
await playController.play()
// playController.play()
// playController.pause()
}}
>
{!state ? '播放' : '暂停'}
</button>
)
}

/**
* 面板:进度条状态
*/
function Panel() {
const [percentage, setPercentage] = React.useState(0)

React.useEffect(() => {
const interval = setInterval(() => {
// duration 可能不精准,建议使用 数据下发的 音频时长
const duration = playController.duration
const currentTime = playController.currentTime

setPercentage(currentTime / duration * 100)
}, 300)

return () => {
if (interval) {
clearInterval(interval)
}
}
}, [])

return (
<div className="PlayController-Panel">
<div className="progress" style={{ width: percentage + '%' }}>
{percentage.toFixed(2) + '%'}
</div>
</div>
)
}

/**
* 您的解析逻辑,以 Five 为例
*/
export function YourHandler() {
const five = unsafe__useFiveInstance()

React.useEffect(() => {
const hanlder = (vreoKeyframe: VreoKeyframe) => {
// 不是自定义类型的剧本帧,不解析
if (vreoKeyframe.type !== VreoKeyframeEnum.Custom) {
return
}
// 是自定义,但不是 经纪人讲房 录制,同样不解析
const data = vreoKeyframe.data
if (data.type !== 'AgentNavigation') {
return
}

// 解析各个字段,执行不同的渲染逻辑
// camera 相机
if (data.camera) {
five.updateCamera({
fov: data.camera.fov,
longitude: data.camera.longitude,
latitude: data.camera.latitude,
}, 0)
}
// position 点位
if (data.position && data.position.panoIndex && data.position.panoIndex !== five.panoIndex) {
five.moveToPano(data.position.panoIndex)
}
}

playController.on(VreoKeyframeEnum.Custom, hanlder)

return () => {
playController.off(VreoKeyframeEnum.Custom, hanlder)
}
}, [])

return <></>
}

export function App() {
return (
<div className="PlayController-App">
<Button />
<Panel />
<YourHandler />
</div>
)
}
29 changes: 29 additions & 0 deletions __test__/PlayController/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.PlayController-Button {
position: fixed;
right: 24px;
top: 24px;
}

.PlayController-Panel {
position: fixed;
height: 42px;
width: 340px;
background-color: #009688;
bottom: 36px;
left: 50%;
transform: translate(-50%, 0);
}

.progress {
position: absolute;
left: 0;
top: 0;
background-color: brown;
color: white;
height: 100%;
width: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
30 changes: 30 additions & 0 deletions __test__/PlayController/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FiveInitArgs, parseWork } from '@realsee/five'
import { createFiveProvider } from '@realsee/five/react'
import * as React from 'react'
import ReactDOM from 'react-dom'
import { ResponsiveFullScreenFiveCanvas } from '../components/ResponsiveFullScreenFiveCanvas'
import work from './work.json'

import '../index.css'
import { App } from './App'

const defaultInitArgs: FiveInitArgs = {
imageOptions: { size: 1024 },
textureOptions: { size: 64 },
onlyRenderIfNeeds: true,
antialias: false,
model: {},
plugins: [],
}

const FiveProvider = createFiveProvider(defaultInitArgs)

ReactDOM.render(
<React.StrictMode>
<FiveProvider initialWork={parseWork(work)} ref={(ref) => Object.assign(window, { $five: ref?.five })}>
<ResponsiveFullScreenFiveCanvas />
<App />
</FiveProvider>
</React.StrictMode>,
document.getElementById('root')
)
Loading

0 comments on commit a8d5951

Please sign in to comment.