ffcreator解读(一)
在
- 第一步调用creator.start()开始执行。
- 在creator.start()中调用了renderer.start()
- 在renderer.start()中有三个关键方法:
- preProcessing()会预处理,抽帧。
- createStream方法创建一个FFStream实例并绑到this.stream
- createSynthesis方法开始执行合成
- 在createSynthesis方法中调用了 synthesis.addStream(stream)。将stream加入其中。
- 在这个方法里,调用了command.addInput(stream)
- 这个方法的本质是将ffstream流添加到ffmpeg。之后ffmpeg命令执行时会从这个流读数据。这个实现是另外一个第三方库fluent-ffmpeg
- 而这个command实际上也是由fluent-ffmpeg创建的
- 在createSynthesis方法中最后调用了synthesis.start()
- 在synthesis.start()中调用了command.run()
- 这个方法本质上是调用了fluent-ffmpeg 的run方法。在这个方法里。ffmpeg开始执行。开始读取流数据了。这样就会触发ffstream._read方法(ffstream继承自nodejs的Readable流,_read是一个内置方法。会在消费端读取数据时触发,而ffstream把这个_read方法重写,用来读取ffcreater创建的数据)
- pipe()方法会读取stream流,触发stream._read(),ffmpegProc.stdin是ffmpeg自己的输入流。这个相当于把inputStream中读到的数据做为ffmpegProc的输入传给ffmpeg。
- 如何将自己的数据传给stream
- 在createStream方法中。有stream.addPullFunc方法,它会将renderFrame绑定到stream
- 顺便一提。这个fillNewData方法,实现了并行处理。就是最后一行
- 在FFStream中重写了Readable._read方法,并在这个方法里读取renderFrame数据。在ffmpeg调用pip()方法时。将数据传过去
- renderFrame如何读取画面信息:
- 渲染封面:
- 在renderFrame中调用了secne.start()。这个方法最终会调用FFVideo的start方法。在ffvideo.start里会调用drawCoverImage()
- 在drawCoverImage()里调用了drawing()
- 值得一提这里第一行的display就是用inkpaint创建的 https://github.com/drawcall/inkpaint
- drawing里调用了getFrame方法得到当前帧需要的图片,并调用display的updateBaseTexture添加进去。
- 在renderFrame中调用了secne.start()。这个方法最终会调用FFVideo的start方法。在ffvideo.start里会调用drawCoverImage()
- 画动画帧:
- 在renderFrame中调用nextFrame方法后,同样会调用drawing方法。这个方法是在Tween里被调用的(ffcreator绑了tween的事件),renderFrame方法会在每一帧绘制时调用,这样会把把最终渲染的图像传给ffmpeg
- 这里绑的事件就是drawing
- 这个事件是在TWEEN.update中绑定的
- 当前时间超过对应的开始时间(delay设定的时间)后,会调用onStartCallback。事件在这里绑定。
- 在TWEEN的onstart事件里调用了ffvideo.addTimelineCallback,把事件绑到了tween上。
- 在TWEEN的onstart事件里调用了ffvideo.addTimelineCallback,把事件绑到了tween上。
- 绑定之后就会每一帧处理都调用drawing了。
- 在renderFrame中调用nextFrame方法后,同样会调用drawing方法。这个方法是在Tween里被调用的(ffcreator绑了tween的事件),renderFrame方法会在每一帧绘制时调用,这样会把把最终渲染的图像传给ffmpeg
- 在renderFrame中调用了 snapshotToBuffer()方法。
- 这个方法用inkpaint渲染,并将渲染结果并写入buffer。
- creator.render调用了inkpaint的render(),这样会把在preProcessing中载入的资源进行渲染,并创建了一个view。再用creator.app.view拿到
- 这个buff会随着renderFrame方法传到FFStream._read()中
- 这样ffmpeg就会读到ffstream流中的数据。直到读到null为止,会一直执行。
- 渲染封面:
- 在createStream方法中。有stream.addPullFunc方法,它会将renderFrame绑定到stream
作者
admin@example.com