Closed ikequan closed 9 months ago
@ikequan Thank you for your attention. Can you package the code of the page into a compressed file ๐ฆ and upload it? This makes it easier for me to check the problem ๐
Ok here is the compressed files. Archive.zip
@ikequan Okay, I've noticed that you're manipulating the currentTime of the video in your code, which isn't actually necessary. I'll need some time to investigate these anomalies.
Yes I am using currentTime to drive the timeline of the animejs to control when the fabricjs obbject moved in
` playFrame() { if (this.playing) { const currentTime = this.getCurrentTime(); this.updateTimeTo(currentTime); // Continue animation if (currentTime < this.duration) { requestAnimationFrame(() => this.playFrame()); } else { this.togglePlay(); } // Render canvas this.canvas.renderAll(); } }
updateTimeTo(newTime) {
this.animationTimeLine.seek(newTime);
if (this.canvas) {
this.canvas.backgroundColor = this.backgroundColor;
}
this.traceObjects.forEach((e) => {
const isInside =
e.timeFrame.start <= newTime && newTime <= e.timeFrame.end;
e.visible = isInside;
if (e.type == "video") {
const videoEl = this.videos.find(
(video) => video.id === e.properties.elementId
);
if (isInside) {
videoEl.play();
} else {
videoEl.pause();
}
}
});
}`
@ikequan I checked these codes and there may be some modifications you need to make ๐ :
Setting currentTime for the <video>
element is actually an inaccurate "seek". For the browser, it is decoded and then drawn asynchronously, so picture synchronization cannot be achieved. WVC solves this problem by replacing the <video>
element added to the DOM tree with the <canvas>
element, and implementing decoding and drawing through VideoDecoder to ensure picture synchronization.
addVideo() {
let video = document.createElement("video");
video.src = "/f3ea9a1d-935d-4eb4-a508-a94d47e77f02-final.mp4";
video.onloadedmetadata = () => {
const id = this.getUid();
video.setAttribute("id", id);
video.style.position = "absolute";
video.style.top = 0;
video.style.left = "300px";
video.style.zIndex = 99;
video.style.width = `${video.videoWidth}px`;
video.style.height = `${video.videoHeight}px`;
// this.videoOject = new fabric.CustomVideo(video, {
// type: "video",
// id: id,
// left: 200,
// top: 0,
// width: video.videoWidth,
// height: video.videoHeight,
// cropRect: null,
// timeFrame: {
// start: 0,
// end: (video.duration * 1000).toFixed(),
// },
// properties: {
// elementId: id,
// },
// });
// this.canvas.add(this.videoOject);
document.getElementsByClassName('canvas-container')[0].append(video);
// this.traceObjects.push(this.videoOject);
// this.videos.push(video);
this.addAnimation({
id: this.getUid(),
type: "slideIn",
targetId: this.videoOject.id ?? "",
duration: 500,
left: 400,
properties: {},
});
// this.updateVideoElements();
};
}
https://github.com/Vinlic/WebVideoCreator/assets/20235341/7fe36d54-5425-497b-9da9-c4765ca79abe
@Vinlic, while i was waiting for your reply, I also removed the fabricjs part and added the video element directly to the dom, and it worked like you did above. In my frontend code(some like canva.com editor), I use fabricjs to add the object to editor and animate them the animejs and now frabricjs implementation of adding video is not compatible with WebVideoCreator, I think I have to build a new frontend UI to add the objects directly to the dom.
@ikequan This does cause some trouble. I have an idea ๐งช but I haven't verified it yet, maybe you can try it:
<canvas src="test.mp4" video-capture></canvas>
First of all thank you for this an amazing project, I saw your comment recommending your project to another user and decided to give it and try. Your render is faster than more of the projects out there so I decided to switch to your project. Everything works fine but the out video seems to like it been fast forward
this my js code using fabric js(for adding two box and a video to canvas) and Anime.js for animating the fabric js objects :
`document.addEventListener("DOMContentLoaded", function () { fabric.CustomVideo = fabric.util.createClass(fabric.Image, { type: "customvideo", cropRect: null,
});
class RenderEngine { constructor() { this.canvas = new fabric.Canvas("canvas"); this.backgroundColor = "#00000"; this.canvas.backgroundColor = this.backgroundColor; let context = this; this.playing = false; this.duration = 40000; // 40 seconds this.startTime = null; this.elapsedTime = 0; this.traceObjects = []; this.videos = []; this.animationTimeLine = anime.timeline(); this.animations = []; this.currentKeyFrame = 0; this.currentTime = 0; this.fps = 60; this.v = document.querySelector("#video-1");
} const _RenderEngine = new RenderEngine(); _RenderEngine.addVideo(); _RenderEngine.togglePlay(); }); `
WebVideoCreator ` import WebVideoCreator, { VIDEO_ENCODER, logger } from "web-video-creator";
const wvc = new WebVideoCreator();
// Configure WVC wvc.config({
compatibleRenderingMode: true,
});
// Create a single-scene video const video = wvc.createSingleVideo({ url: "http://127.0.0.1:5500/fabric-anim-export.html",
});
// Listen for the completion event video.once("completed", result => { logger.success(
Render Completed!!!\nvideo duration: ${Math.floor(result.duration / 1000)}s\ntakes: ${Math.floor(result.takes / 1000)}s\nRTF: ${result.rtf}
) });// Start rendering video.start(); `
sample videos: My browser
https://github.com/Vinlic/WebVideoCreator/assets/86013106/8923f21a-bc10-45dd-b463-d151a6a901a2
WebVideoCreator output
https://github.com/Vinlic/WebVideoCreator/assets/86013106/134795ee-656c-4bac-babe-4964b6b94eef