# JS2Video URL: https://js2video.com ## Video Templates Video Templates are written in JavaScript and exports a template function and the default params. Our engine executes the template function with the default params + user params and renders a video on the client or server. ## Video Template Examples Use this examples to modify / create your video templates. ### audio-waveform-bars.js ```javascript /* Load audio from URL and display waveform bars */ const defaultParams = { audioUrl: "https://js2video.com/audio/audio.mp3", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#ff0200" }); // load audio from URL const audio = await canvasUtils.loadAudio({ url: params.audioUrl }); // add audio to canvas canvas.add(audio); // analyze audio waveform const analyzedAudio = await utils.analyzeAudio({ url: params.audioUrl, audioBuffer: audio.js2video_audioBuffer, fps: params.fps, fftSize: 16384, minDb: -90, maxDb: -10, audioSmoothing: 0.2, minFreq: 40, maxFreq: 300, numberOfBins: 32, }); // display waveform bars const waveform = await canvasUtils.loadWaveformBars({ audio: analyzedAudio, paddingInner: 0.2, paddingOuter: 0, orientation: "vertical", anchor: "center", roundedCaps: true, options: { fill: "#ffffff", width: params.size.width * 0.5, height: params.size.height * 0.9, originY: "center", originX: "center", }, duration: audio.js2video_duration, }); canvas.add(waveform); // put bars in center canvas.centerObject(waveform); // create animation in the duration of the audio timeline.to({}, { duration: audio.js2video_duration }, 0); }; export { template, defaultParams }; ``` ### bg-image.js ```javascript /* Background image with text overlay */ const defaultParams = { text: "Don't panic!", imageUrl: "https://js2video.com/images/ocean.jpg", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load image from URL const image = await canvasUtils.loadImage({ url: params.imageUrl, options: { originX: "center", originY: "center", }, }); // add image to canvas canvas.add(image); // scale video to cover canvas canvasUtils.scaleToCoverCanvas(image, canvas); // center video on canvas canvas.centerObject(image); // load text object const text = await canvasUtils.loadText({ text: params.text, options: { fontSize: 200, fontFamily: "sans-serif", fill: "white", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // scale up image a bit timeline.to( image, { scaleX: image.scaleX * 1.2, scaleY: image.scaleY * 1.2, duration: 5, ease: "linear", }, 0 ); // fade out text timeline.to(text, { opacity: 0, duration: 5 }, 0); }; export { template, defaultParams }; ``` ### chars.js ```javascript /* Animate text as separate characters */ const defaultParams = { text: "The ships hung in the sky in much the same way that bricks don't.", fontFamily: "Liter", fps: 30, size: { width: 1080, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#000000" }); // load Google font by name await utils.loadGoogleFont(params.fontFamily); // load text object const text = await canvasUtils.loadChars({ canvas, text: params.text, options: { width: canvas.width * 0.8, fontSize: 120, fontWeight: "bold", fontFamily: params.fontFamily, fill: "white", textAlign: "center", }, }); // center text on canvas canvas.centerObject(text); // animate chars timeline .from(text._objects, { left: "-=100", top: 0, opacity: 0, duration: 0.1, stagger: 0.02, ease: "back", duration: 1, }) .to(text._objects, { delay: 1, opacity: 0, duration: 0.5, stagger: { each: 0.02, from: "random", }, }); }; export { template, defaultParams }; ``` ### confetti.js ```javascript /* Animated confetti from SVG */ const defaultParams = { text: "You Made It!", fontFamily: "Bangers", fps: 30, size: { width: 1080, height: 1920, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set bg color canvas.set({ backgroundColor: "#111111" }); // load Google font by name await utils.loadGoogleFont(params.fontFamily); // load text object const text = await canvasUtils.loadTextbox({ text: params.text, options: { width: params.size.width * 0.8, fontSize: 180, fontFamily: params.fontFamily, fill: "#ffffff", textAlign: "center", }, }); text.set({ originX: "center", originY: "center" }); // add + center text canvas.add(text); canvas.centerObject(text); // animate text timeline.from(text, { opacity: 0, scaleX: 0.01, scaleY: 0.1, duration: 0.8, ease: "elastic", }); // load svg from url const svg = await canvasUtils.loadSvg({ url: "/svg/confetti.svg" }); // scale + center svg canvasUtils.scaleToCoverCanvas(svg, canvas, 1.1); canvas.centerObject(svg); // get confetti "strings" const confettis = svg.getObjects(); // animate them confettis.map((confetti) => { const length = utils.lerp( 100, Math.max(params.size.width, params.size.height), Math.random() ); const pathLength = canvasUtils.getSvgPathLength(confetti.path); canvas.add(confetti); confetti.set({ objectCaching: false, }); timeline.fromTo( confetti, { stroke: utils.randomColor(), strokeDashArray: [length, pathLength], strokeWidth: utils.lerp(3, 60, Math.random()), strokeDashOffset: pathLength + length * 2, }, { strokeDashOffset: length, delay: utils.lerp(0, 0.4, Math.random()), duration: utils.lerp(1, 3, Math.random()), ease: "power4.out", repeat: 1, repeatDelay: 0.5, }, 0 ); }); }; export { template, defaultParams }; ``` ### counter.js ```javascript /* Animate a counter */ const defaultParams = { fontFamily: "Space Mono", from: "0", to: "53.9", prefix: "", postfix: "%", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#204440" }); // create a formatter from the number const formatter = new Intl.NumberFormat("en-US", { minimumIntegerDigits: 2, minimumFractionDigits: 1, maximumFractionDigits: 1, }); // load google font await utils.loadGoogleFont(params.fontFamily); // load text object const text = await canvasUtils.loadText({ text: params.from, options: { fontSize: 300, fontFamily: params.fontFamily, fontWeight: "bold", fill: "#ffffff", originX: "center", originY: "center", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // animate counter timeline.fromTo( text, { text: params.from }, { text: params.to, duration: 8, modifiers: { text: function (value, obj) { obj.set({ text: params.prefix + formatter.format(value + "") + params.postfix, }); }, }, ease: "expo.inOut", }, 0 ); // add some pause at the end timeline.to({}, { duration: 2 }); }; export { template, defaultParams }; ``` ### custom-font.js ```javascript /* Load custom font by URL */ const defaultParams = { text: "Don't panic!", fontUrl: "https://js2video.com/fonts/calsans-semibold.woff2", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#1f7dff" }); // load font from URL const fontFamily = await utils.loadFont(params.fontUrl); // load text object const text = await canvasUtils.loadText({ text: params.text, options: { fontSize: 200, fontFamily: fontFamily, fill: "#000000", originX: "center", originY: "center", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // animate text in - out timeline .from(text, { scaleX: 0, scaleY: 0, duration: 0.5, delay: 0.2, ease: "elastic", }) .to(text, { opacity: 0, duration: 2, delay: 1, ease: "expo.out", }); }; export { template, defaultParams }; ``` ### elevenlabs-tts-subtitles.js ```javascript const defaultParams = { elevenLabsDataUrl: "https://js2video.com/elevenlabs/speech-1.json", imageUrl: "https://js2video.com/images/ai/axolotl.jpeg", fontFamily: "Baloo", fps: 30, size: { width: 1080, height: 1920, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load image from URL const image = await canvasUtils.loadImage({ url: params.imageUrl, options: { originX: "center", originY: "center", }, }); // add, scale and center image canvas.add(image); canvasUtils.scaleToCoverCanvas(image, canvas); canvas.centerObject(image); // load gogle font by name await utils.loadGoogleFont(params.fontFamily); // create text for subtitles const textObject = await canvasUtils.loadTextbox({ text: "", options: { width: params.size.width * 0.8, fontFamily: params.fontFamily, fontSize: 120, originX: "center", originY: "center", left: params.size.width * 0.5, top: params.size.height * 0.8, textAlign: "center", fontWeight: "bold", stroke: "black", fill: "#ddff00", strokeWidth: 8, paintFirst: "stroke", }, }); // add text obj to canvas canvas.add(textObject); // load audio and subtitles await canvasUtils.loadElevenLabsSpeech({ timeline, canvas, dataUrl: params.elevenLabsDataUrl, textObject, modifyText: (text) => text.toUpperCase(), offset: 0.5, minDuration: 0.4, animateFrom: { opacity: 0, scaleX: 0.6, scaleY: 0.6 }, animateTo: { duration: 0.2, opacity: 1, scaleX: 1, scaleY: 1, ease: "back", }, }); // add some pause at the end timeline.to({}, { duration: 1 }); // scale up image timeline.to( image, { scaleX: image.scaleX * 1.2, scaleY: image.scaleY * 1.2, duration: timeline.duration(), ease: "linear", }, 0 ); }; export { template, defaultParams }; ``` ### google-font.js ```javascript /* Load Google font by name */ const defaultParams = { text: "The ships hung in the sky in much the same way that bricks don't.", fontFamily: "Krona One", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#a284fa" }); // load Google font by name await utils.loadGoogleFont(params.fontFamily); // load text object const text = await canvasUtils.loadTextbox({ text: params.text, options: { width: 1200, fontSize: 120, fontFamily: params.fontFamily, fill: "#ffffff", textAlign: "center", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // animate text in - out timeline .from(text, { opacity: 0, duration: 1, }) .to(text, { opacity: 0, duration: 1, delay: 2, }); }; export { template, defaultParams }; ``` ### hello-world.js ```javascript const defaultParams = { name: "Unknown", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#0000ee" }); const text = await canvasUtils.loadText({ text: `Hello ${params.name}!`, options: { fontSize: 200, fontFamily: "sans-serif", fill: "white", originX: "center", originY: "center", }, }); canvas.add(text); canvas.centerObject(text); timeline.from(text, { scaleX: 0, scaleY: 0, duration: 0.5, delay: 0.2, ease: "elastic", }); timeline.to(text, { opacity: 0, duration: 2, delay: 1, ease: "expo.out", }); }; export { template, defaultParams }; ``` ### horizontal-gradient.js ```javascript /** Horizontal Background Gradient */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { const gradient = new Fabric.Gradient({ type: "linear", coords: { x1: 0, y1: 0, x2: params.size.width, y2: 0 }, colorStops: [ { offset: 0, color: "#ff69b4" }, // hot pink { offset: 1, color: "#39ff14" }, // neon green ], }); canvas.set({ backgroundColor: gradient }); timeline.to({}, { duration: 5 }); }; export { template, defaultParams }; ``` ### lottie-emoji.js ```javascript /* Load Lottie animation from URL */ const defaultParams = { lottieUrl: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f92f/lottie.json", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set canvas background color canvas.set({ backgroundColor: "papayawhip" }); // load lottie animation from URL const lottie = await canvasUtils.loadLottie({ url: params.lottieUrl, options: { width: params.size.width / 2, height: params.size.height / 2, }, }); // add/center lottie animation on canvas canvas.add(lottie); canvas.centerObject(lottie); // create a dummy animation as long as the lottie animation timeline.to({}, { duration: lottie.js2video_lottie.duration }); }; export { template, defaultParams }; ``` ### pixi.js ```javascript /* Load Pixi */ const defaultParams = { fontFamily: "Bangers", lottieUrl: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f92f/lottie.json", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { const pixi = await canvasUtils.loadPixi({ canvas }); canvas.add(pixi); const text = new Pixi.HTMLText({ text: "This is a

HAHA

styled
text! a", style: { fontSize: 120, fontWeight: 650, fill: "yellow", }, }); pixi.js2video_app.stage.addChild(text); // const filter = new PixiFilters.AsciiFilter({ size: 28 }); // pixi.js2video_app.stage.filters = [filter]; // create a dummy animation as long as the lottie animation timeline.to({}, { duration: 2 }, 0); }; export { template, defaultParams }; ``` ### svg-string.js ```javascript /* Load SVG from string */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#e9e9e9" }); // load SVG from string const svg = await canvasUtils.loadSvgFromString({ string: ` `, options: { originX: "center", originY: "center", }, }); // add/scale/center SVG canvas.add(svg); canvasUtils.scaleToFitCanvas(svg, canvas); canvas.centerObject(svg); // animate SVG timeline.to(svg, { angle: 360, duration: 6 }); }; export { template, defaultParams }; ``` ### text-glitch-filter.js ```javascript /* Text with glitch + blur filter https://pixijs.io/filters/docs/GlitchFilter.html https://pixijs.io/filters/docs/KawaseBlurFilter.html */ const defaultParams = { text: "SAN DIEGO 1992", fontFamily: "Liter", // Google Font imageUrl: "https://js2video.com/images/ai/beach.jpg", // AI-generated fps: 30, size: { width: 1280, height: 960, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // generates a random number within a specified range, ensuring // the change from the current value does not exceed maxChange. function random2(current, min, max, maxChange) { const lowerBound = Math.max(min, current - maxChange); const upperBound = Math.min(max, current + maxChange); return Math.random() * (upperBound - lowerBound) + lowerBound; } // create a random number const random = (from, to) => utils.lerp(from, to, Math.random()); // set background color canvas.set({ backgroundColor: "#000088" }); // load Google font by name await utils.loadGoogleFont(params.fontFamily); // load image from URL const image = await canvasUtils.loadImage({ url: params.imageUrl, options: { originX: "center", originY: "center", opacity: 0.4, }, }); // add image to canvas canvas.add(image); // scale video to cover canvas canvasUtils.scaleToCoverCanvas(image, canvas); // center video on canvas canvas.centerObject(image); // load text object const text = await canvasUtils.loadTextbox({ text: params.text, options: { width: params.size.width * 0.5, fontSize: 60, fontFamily: params.fontFamily, fontWeight: "bold", fill: "#ffffff", textAlign: "center", }, }); // add text to canvas, scale and center canvas.add(text); canvasUtils.scaleToFitCanvas(text, canvas, 0.9); canvas.centerObject(text); const filters = []; const glitchFilter = new PixiFilters.GlitchFilter({ slices: 20, offset: 10, green: { x: 10, y: 10 }, }); filters.push(glitchFilter); const blurFilter = new PixiFilters.KawaseBlurFilter(); filters.push(blurFilter); const pixiFilters = await canvasUtils.loadPixiFilters({ canvas, filters }); canvas.add(pixiFilters); pixiFilters.set({ left: params.size.width * 0.5, top: 0, scaleX: 1.1, scaleY: 1.1, originX: "center", }); // scale up image a bit timeline.to( image, { scaleX: image.scaleX * 1.2, scaleY: image.scaleY * 1.2, duration: 5, ease: "linear", }, 0 ); // animate filter properties timeline.to( {}, { duration: 5, onUpdate: () => { filters.map((f) => { f.slices = parseInt(random(18, 22)); f.offset = random2(f.offset, -10, 10, 2); f.strength = random2(f.strength, 0, 1, 0.1); f.green = { x: random(0, 12), y: 0 }; }); }, }, 0 ); }; export { template, defaultParams }; ``` ### transition-fade.js ```javascript /* Transition: fade in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // add transitions timeline.fadeIn(obj).fadeOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-scale-down.js ```javascript /* Transition: scale down in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", originX: "center", originY: "center", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // scale down in/out timeline.scaleDownIn(obj).scaleDownOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-scale-up.js ```javascript /* Transition: scale up in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", originX: "center", originY: "center", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // scale down in/out timeline.scaleUpIn(obj).scaleUpOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-slide-down.js ```javascript /* Transition: slide down in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // slide down in/out timeline.slideDownIn(obj).slideDownOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-slide-left.js ```javascript /* Transition: slide left in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // slide left in/out timeline.slideLeftIn(obj).slideLeftOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-slide-right.js ```javascript /* Transition: slide left in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // slide right in/out timeline.slideRightIn(obj).slideRightOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### transition-slide-up.js ```javascript /* Transition: slide up in/out */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { canvas.set({ backgroundColor: "#f3f8fb" }); const obj = new Fabric.Rect({ width: 200, height: 200, scaleX: 2, scaleY: 2, fill: "#ff1d63", }); // add object to canvas canvas.add(obj); canvas.centerObject(obj); // slide up in/out timeline.slideUpIn(obj).slideUpOut(obj, { delay: 1 }); }; export { template, defaultParams }; ``` ### typewriter.js ```javascript /* Write a text in a typewriter style */ const defaultParams = { text: "Are we human?", fontFamily: "Space Grotesk", cursor: "▎", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "#fefb9f" }); // load google font await utils.loadGoogleFont(params.fontFamily); // load text object const text = await canvasUtils.loadTextbox({ text: "", options: { width: params.size.width * 0.8, fontSize: 140, fontFamily: params.fontFamily, fontWeight: "bold", fill: "#000000", originX: "center", originY: "center", textAlign: "center", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // split text into chars const seg = new Intl.Segmenter("en", { granularity: "grapheme" }); const chars = [...seg.segment(params.text)].map((s) => s.segment); // animate chars timeline.to( text, { text: "", duration: chars.length * 0.1, modifiers: { text: function (value, obj) { const charsToShow = Math.floor( utils.lerp(0, chars.length, this.progress()) ); obj.set({ text: !charsToShow ? "" : chars.slice(0, charsToShow).join("") + params.cursor, }); }, }, }, 0 ); // add some pause at the end timeline.to({}, { duration: 3 }); }; export { template, defaultParams }; ``` ### vertical-gradient.js ```javascript /** Vertical Background Gradient */ const defaultParams = { fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { const gradient = new Fabric.Gradient({ type: "linear", coords: { x1: 0, y1: 0, x2: 0, y2: params.size.height }, colorStops: [ { offset: 0, color: "#ff69b4" }, // hot pink { offset: 1, color: "#39ff14" }, // neon green ], }); canvas.set({ backgroundColor: gradient }); timeline.to({}, { duration: 5 }); }; export { template, defaultParams }; ``` ### video-adjustment-filter.js ```javascript /* Background video with an adjustment filter https://pixijs.io/filters/docs/AdjustmentFilter.html */ const defaultParams = { videoUrl: "https://js2video.com/video/bbb.mp4", fps: 30, size: { width: 1920, height: 1080, }, filter: { alpha: 1, blue: 1.05, brightness: 1.2, contrast: 0.85, gamma: 1.1, green: 1.05, red: 1.15, saturation: 3.1, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load video from URL const video = await canvasUtils.loadVideo({ url: params.videoUrl, options: { originX: "center", originY: "center", }, }); canvas.add(video); canvasUtils.scaleToCoverCanvas(video, canvas); canvas.centerObject(video); const filters = []; // https://pixijs.io/filters/docs/AdjustmentFilter.html const adjustmentFilter = new PixiFilters.AdjustmentFilter(params.filter); filters.push(adjustmentFilter); const pixiFilters = await canvasUtils.loadPixiFilters({ canvas, filters, }); canvas.add(pixiFilters); // create a no-op animation with the duration of the video timeline.to( {}, { duration: video.js2video_duration, }, 0 ); }; export { template, defaultParams }; ``` ### video-colormatrix-filter.js ```javascript /* Background video with a custom colorMatrix filter https://pixijs.download/dev/docs/filters.ColorMatrixFilter.html */ const defaultParams = { videoUrl: "https://js2video.com/video/bbb.mp4", fps: 30, size: { width: 1920, height: 1080, }, matrix: [ 1.9125277891456083, -0.8545344976951645, -0.09155508482755585, 0, 11.793603434377337, -0.3087833385928097, 1.7658908555458428, -0.10601743074722245, 0, -70.35205161461398, -0.231103377548616, -0.7501899197440212, 1.847597816108189, 0, 30.950940869491138, 0, 0, 0, 1, 0, ], }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load video from URL const video = await canvasUtils.loadVideo({ url: params.videoUrl, options: { originX: "center", originY: "center", }, }); canvas.add(video); canvasUtils.scaleToCoverCanvas(video, canvas); canvas.centerObject(video); const filters = []; const colorMatrixFilter = new Pixi.ColorMatrixFilter(); // color matrix for TechniColor // you can ask a LLM to create these for you! colorMatrixFilter._loadMatrix(params.matrix, true); filters.push(colorMatrixFilter); const pixiFilters = await canvasUtils.loadPixiFilters({ canvas, filters }); canvas.add(pixiFilters); // create a no-op animation with the duration of the video timeline.to( {}, { duration: video.js2video_duration, }, 0 ); }; export { template, defaultParams }; ``` ### video-filtermask.js ```javascript /* Background video with a custom colorMatrix filter https://pixijs.download/dev/docs/filters.ColorMatrixFilter.html */ const defaultParams = { videoUrl: "https://js2video.com/video/bbb.mp4", fps: 30, size: { width: 1920, height: 1080, }, filter: { alpha: 1, blue: 1, brightness: 1, contrast: 3, gamma: 1, green: 1, red: 1, saturation: 0, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load video from URL const video = await canvasUtils.loadVideo({ url: params.videoUrl, options: { originX: "center", originY: "center", }, }); canvas.add(video); canvasUtils.scaleToCoverCanvas(video, canvas); canvas.centerObject(video); const filters = []; // https://pixijs.io/filters/docs/AdjustmentFilter.html const adjustmentFilter = new PixiFilters.AdjustmentFilter(params.filter); filters.push(adjustmentFilter); const pixiFilters = await canvasUtils.loadPixiFilters({ canvas, filters, }); const mask = new Fabric.Circle({ originX: "center", originY: "center", left: params.size.width * 0.5, top: params.size.height * 0.5, radius: Math.min(params.size.height, params.size.width) * 0.5 * 0.8, absolutePositioned: true, }); // add filter mask pixiFilters.set({ clipPath: mask, }); canvas.add(pixiFilters); // animate the mask timeline.fromTo( mask, { left: 0 }, { left: params.size.width, duration: video.js2video_duration, }, 0 ); }; export { template, defaultParams }; ``` ### video-overlay.js ```javascript /* Background video with text overlay */ const defaultParams = { text: "Don't panic!", videoUrl: "https://js2video.com/video/bbb.mp4", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // set background color canvas.set({ backgroundColor: "green" }); // load video from URL const video = await canvasUtils.loadVideo({ url: params.videoUrl, options: { originX: "center", originY: "center", }, }); // add video to canvas canvas.add(video); // scale video to fit canvas canvasUtils.scaleToFitCanvas(video, canvas); // center video on canvas canvas.centerObject(video); // load text object const text = await canvasUtils.loadText({ text: params.text, options: { fontSize: 200, fontFamily: "sans-serif", fill: "white", }, }); // add text to canvas canvas.add(text); // center text on canvas canvas.centerObject(text); // create a no-op animation with the duration of the video timeline.from( video, { scaleX: 0.1, scaleY: 0.2, opacity: 0, duration: 1.2, ease: "elastic", }, 0 ); // create a no-op animation with the duration of the video timeline.to( {}, { duration: video.js2video_duration, }, 0 ); }; export { template, defaultParams }; ``` ### video-pixi-filter.js ```javascript /* Background video with old film filter https://pixijs.io/filters/docs/ */ const defaultParams = { videoUrl: "https://js2video.com/video/bbb.mp4", fps: 30, size: { width: 1920, height: 1080, }, }; const template = async ({ gsap, timeline, canvas, canvasElement, params, Fabric, Pixi, PixiFilters, utils, canvasUtils, }) => { // load video from URL const video = await canvasUtils.loadVideo({ url: params.videoUrl, options: { originX: "center", originY: "center", }, }); canvas.add(video); canvasUtils.scaleToCoverCanvas(video, canvas); canvas.centerObject(video); const oldFilmFilter = new PixiFilters.OldFilmFilter({ sepia: 1, noise: 0.1, noiseSize: 2, seed: Math.random(), scratchWidth: 8, vignettingAlpha: 0.2, }); const filters = [oldFilmFilter]; const pixiFilters = await canvasUtils.loadPixiFilters({ canvas, filters }); canvas.add(pixiFilters); // create a no-op animation with the duration of the video timeline.to( {}, { duration: video.js2video_duration, onUpdate: () => { filters.map((f) => (f.seed = Math.random())); }, }, 0 ); }; export { template, defaultParams }; ```