remotion-dev/remotion

Dynamically set `width` and `height` & FPS #808

tomByrer posted onGitHub

Edit by @JonnyBurger:

šŸŽƒ This issue is part of our Hacktoberfest campaign! šŸ“š Read more about Hacktoberfest here āœ… This issue is currently assigned to @exitflynn!

Hacktoberfest acceptance criteria:

  • Should introduce new height and width flags for renderMediaOnLambda() and renderStillOnLambda() (it is not required for renderMedia() and renderStill() since you can override the composition object)
  • Should introduce a new --height and --width flag to be used for the npx remotion render, npx remotion still, npx remotion lambda render and npx remotion lambda still commands.
  • These flags will override the width and height of the render regardless of what was passed to <Composition>.
  • Some restrictions apply: For h264 videos, the dimensions must be even (divisible by 2), must be integer and not negative. This is currently validated and one should not be able to bypass that validation
  • Document the feature in all API pages where those options can be passed

Original issue:

Use Case

Rapidly changing FPS & video size for:

  • local development vs final product
  • multiple hosting target sizers (eg Social media)
  • dynamic <Player> playback (Responsive, keep in sync with imbedded video)
  • Changing FPS when source data is in seconds (eg WebVTT)

Problem

While it is clear Remotion uses Frames and FramesPerSecond for time, & pixels for size, these are inconvenient standards for dynamic situations. For example, the movie producer, SEO professional, etc who wants to change the video size & rate easily can not when the components hard-coded.

While everyone could hard-code their own way of handling translations, it would hinder sharing components & complicate development.

Possible Solutions

Unsure best way forward; here is a brainstorm of easiest to complex implementation:

  • Document better, with more examples of dynamic sizes/FPS
  • Standardized helper functions, eg secondsToFrames(), viewhightToPixels() (I'm about to try this)
  • Remotion bakes in automatic conversions similar to CSS units (interpolate(frame, [0, 2sec], [15vw, 50vw]))

I'll break the issue down into it's parts:

  • Dynamically changing the dimensions of the video at render time is something we are exploring to support. It already works with the Node.JS APIs, but it would be cool to do it via the CLI as well.

Note: For now, you can create two compositions with the same component but different dimensions. If you want to create a responsive video, this is cool, because you can preview both styles.

  • A hook called useCurrentTime() was already proposed to return the time in seconds, but I decided against it. Essentially, I want one standard that is used across all tutorials and libraries that are build on top of Remotion. We can more easily share code with each other and no conversion is needed when integrating libraries. The good news is that if you need it, you can trivially implement it yourself.

  • Already explored support for vh and vw but it also has big drawbacks: https://github.com/remotion-dev/remotion/issues/547

  • For interpolate to support seconds, it would have to plug into React context to get the fps value. So we'd have to make it a hook useInterpolate and it has to obey by the rules of hooks. It would be less versatile that it is now and require a migration.

posted by JonnyBurger about 3 years ago

create two compositions with the same component but different dimensions

I'm trying to avoid this, but sometimes might be needed, eg if the aspect ratio changes radically between YouTube & FaceBook/Instagram/TickTok.

The other suggestions are good, but I might have different ideas, so I guess I'll have to build demos.

posted by tomByrer about 3 years ago

I changed the title due to one of my use cases, which is actually my primary concerns:

  • dynamic playback (Responsive, keep in sync with imbedded video)
  • Changing FPS when source data is in seconds (eg WebVTT)

But I failed in being too vague. My main use for Remotion is to use it along with typical videos (eg from YouTube, Vimo, etc):

  • transcript/captions player, either as overlay on top of video, or outside the video.
  • dynamic web pages, which will have to also be responsive

I do have use cases for rendering to different social media platforms, but that is not my main worry.

posted by tomByrer about 3 years ago

Past my bedtime so sorry for being terse, but here is a demo I've worked on: https://github.com/tomByrer/remotion-demo-compose

Quick code examples:

// id, width, height are calculated
// fps default is 30
//TODO: send total time from <Series> to parent <Composition>
<Helper.AdvancedComposition
  component={AboutRemotion}
  durationInSeconds={14}
  resolution='story'
/>
/* useConvert.js */
import {useVideoConfig} from 'remotion'

export function seconds(sec){
    const videoConfig = useVideoConfig()
    return sec * videoConfig.fps
}

export function vh(h){
    const videoConfig = useVideoConfig()
    return h * videoConfig.height * 0.01
}

export function vw(w){
    const videoConfig = useVideoConfig()
    return w * videoConfig.width * 0.01
}
...
/* useAnimation.js */
import {interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion'
import * as useConvert from '../helpers/useConvert';

export function fadeIn(seconds=0.5){
    const frame = useCurrentFrame()
    return interpolate(
        frame,
 // frames conversions makes changing FPS instant
// & seconds are easier to wrap mind around
        [0, useConvert.seconds(seconds)],
        [0, 1]
    )
}
...
/* 
/* SomeComponant.jsx */
import * as useConvert from '../helpers/useConvert';
// although the viewport ratios are hard to read, they are responsive
<div style={{
    fontSize: useConvert.vw(3.7234),
    bottom: useConvert.vh(12.9629),
    opacity: useAnimation.useFadeIn(),
}}
>test div</div>
posted by tomByrer about 3 years ago

@jonnyburger has funded $111.00 to this issue.


posted by issuehunt-app[bot] over 2 years ago

@jonnyburger has funded $1.00 to this issue.


posted by issuehunt-app[bot] over 2 years ago

@remotion-dev has funded $55.00 to this issue.


posted by issuehunt-app[bot] over 2 years ago

Hi @JonnyBurger I'd love to take up this issue!

posted by exitflynn over 2 years ago

@exitflynn Assigned! Good luck!

posted by JonnyBurger over 2 years ago

hello! this one's taking me a bit longer than i expected, still on it though!

posted by exitflynn over 2 years ago

hello there! :wave: i must admit that i was very much a newbie when it came to React and contributing to Open-Source in general when I took this issue up. I had seen the fireship video on Remotion and found the idea to be really neat. While I wanted to start contributing to open-source this hacktoberfest, I decided to search my history for nice repo's I had saved for later, remotion came up and with the added motivation of the issuehunt and the hacktoberfest tags, this issue seemed doable for me. I have been building my React knowledge since then and finally recently managed to start making some progress :cowboy_hat_face: :partying_face: (while managing my college and some volunteering work on the side). I'm not sure why but i just felt like letting you know, this is my first time contributing to a repo in a way that is not non-code :sweat_smile:

posted by exitflynn over 2 years ago

I wanted to clarify which option would be more suitable, putting the setHeight and getHeight under Rendering or under the Output configType? (for reference)

posted by exitflynn over 2 years ago

@exitflynn That's awesome to hear! Love to hear a story of someone getting successfully started!

Both seems okay, if uncertain, you can put it in Config.Output!

posted by JonnyBurger over 2 years ago

Thank you soo much for that response!

Apologies but major beginner question ahead, I am having trouble being able to figure out how to access the hardcoded values like the height and width of the video which the user would have specified. I am currently thinking that they'd be the ones in internals and could be accessed like so:

const video = Internals.useVideo();
const height = video.height;

But since I am to work with the lambda cli functions, an inner voice inside me felt a little uneasy that I am not even touching the lambda directory. I am unable to figure out if the changes made in cli/ carry over to lambda/ cli commands, with just the added lambda prefix or is some sort of bridging or rewriting is necessary, I'm really sorry if the question is too abstract and/or broad and would really appreciate any feedback.

posted by exitflynn over 2 years ago

@exitflynn Sure!

Using useVideo() you only access the height and width once they have been set. The scope of the issue is to define the height and width explicitly before they even reach useVideo().

Check out this location in the codebase: https://github.com/remotion-dev/remotion/blob/main/packages/cli/src/render.tsx#L187

In the config variable, we have various metadata such as width, height and fps. They get pulled from your React code - here it would be great as a first step to, if someone passes --width or --height in the command line, ignore those values and overwrite the config object! Check out the parse-command-line.ts file as well and the variable parsedCli that it exposes.

That is actually already a significant part of the functionality, the other part is to just port it to also to the still and lambda commands and to then update the documentation!

posted by JonnyBurger over 2 years ago

hey jonny! Thanks again for the response. So, I came up with that ^, and just wanted to make sure if this works just in case there's something here that I'm fundamentally missing.

edit: PR #1427 :cowboy_hat_face:

posted by exitflynn over 2 years ago

@jonnyburger has rewarded $150.30 to @exitflynn. See it on IssueHunt

  • :moneybag: Total deposit: $167.00
  • :tada: Repository reward(0%): $0.00
  • :wrench: Service fee(10%): $16.70
posted by issuehunt-app[bot] over 2 years ago

Fixed by #1427

posted by JonnyBurger over 2 years ago

@JonnyBurger Hey man, I just wanted to ask how can I dynamically set height in renderMedia() @tomByrer said above that you can override the composition object, how can I do that?

selectComposition() should have a width and height props to configure this, but there isnt. What other way do I have to do acheive this

posted by ammar-bay over 1 year ago

@ammar-bay renderMediaOnLambda has

forceHeight: body.height,
forceWidth: body.width,
posted by leonmak about 1 year ago

Fund this Issue

$167.00
Rewarded

Rewarded pull request

Recent activities

exitflynn was rewarded by jonnyburger for remotion-dev/remotion# 808
over 2 years ago
exitflynn submitted an output to  remotion-dev/ remotion# 808
over 2 years ago