react-native-camera
react-native-camera copied to clipboard
Ability to set video resolutions (videoFrameWidth & videoFrameHeight)
It adds the ability to set videoFrameWidth
and videoFrameHeight
.
Test Plan Recorded two videos, 1 with the desired resolutions and other without setting them at all. 2nd test is it make sure that it still works as it used to previously.
Test 1
const video = await cameraRef.recordAsync({ mute: true, quality: '4:3', videoFrameWidth: 1280, videoFrameHeight: 960 });
Test 2
const video = await cameraRef.recordAsync({ mute: true, quality: '4:3' });
Nice! Do you think we can proceed to merge this @MarcoScabbiolo?
I'm sorry I forgot to mention that it is Android only. I don't have iPhone, I can fix it later for iOS too.
Another thing I would like to mention is that the resolution should be supported by the device otherwise it would fail to record. For that we need to expose getSupportedVideoSizes(). I have looked into OpenCamera source code to see how it generates the list of supported video sizes, I'm currently working on that (Will create another PR for that).
I think it will be best if you add the method to get the supported sizes to this PR, so the feature is complete once released. Mainly because of the many differences across Android devices.
Sure I can do that.
Does this replace setting quality='480p'
or 720? How does these new props interact with the quality setting? As far as I know, the quality value already sets the video resolution/frame, doesn't it?
With this change we can deprecate 4:3
. Each quality setting maps to one of the CamcorderProfile. 4:3
(i.e. VIDEO_4x3) is a special quality that maps to QUALITY_480P (which is 480x720) and sets the videoFrameWidth to 640.
As far as I know, the quality value already sets the video resolution/frame, doesn't it?
Correct but all those profiles are 16:9. With this PR the width/height can be overridden to get the desired aspect ratio. For example: Currently it is not possible to record in high quality with aspect ratio of 4:3
.
I see, I'm slightly confused, but when I set 4:3
I always get consistent videos in either 720p or 480p (with different aspect rations for each quality, basically 4:3
is ignored right now?). Is ratio='4:3'
even used when recording videos?
What would happen to iOS?
I have added getAvailableVideoSizes()
. It can be called like:
const videoSizes = await cameraRef.getAvailableVideoSizes();
console.log(videoSizes);
(Note: The result is for the ratio set in <RNCamera ratio={ratio} ... />
)
The sample output is:
["320x240", "640x480", "960x720", "1280x960", "1440x1080"]
I originally wanted to return json (width & height in their own fields) instead of string but decided to keep it consistent with getAvailablePictureSizes()
output. I would prefer to return json, I can make the change if that is ok? After change output will be like:
[{"height": 240, "width": 320}, {"height": 480, "width": 640}, {"height": 720, "width": 960}, {"height": 960, "width": 1280}, {"height": 1080, "width": 1440}]
Isn't ratio
an actual aspect ratio ("4:3", "16:9") ?
Does this mean that we need to we will need to "parse" the results in order to set videoFrameWidth and videoFrameHeight? It's probably a better idea to return a JSON as you mentioned.
Isn't
ratio
an actual aspect ratio ("4:3", "16:9") ?
Yes, it is actual aspect ratio.
Does this mean that we need to we will need to "parse" the results in order to set videoFrameWidth and videoFrameHeight? It's probably a better idea to return a JSON as you mentioned.
Right, I did it to be consistent with getAvailablePictureSizes()
. Let me change it to json.
@makzee what will be the behaviour if invalid values are set? Have you also tried with all available cameras (front, back)?
@makzee what will be the behaviour if invalid values are set? Have you also tried with all available cameras (front, back)?
When invalid values are set, it returns an error. Yes I have tested with both the cameras, it works fine.
I have added getAvailableVideoSizes()
. Call it like:
const sizes = await cameraRef.getAvailableVideoSizes();
Reponse:
[{"height": 240, "width": 320}, {"height": 480, "width": 640}, {"height": 720, "width": 960}, {"height": 960, "width": 1280}, {"height": 1080, "width": 1440}]
It is ready to be reviewed and merged.
@cristianoccazinsp, @MarcoScabbiolo do you think we can go on merging this?
It looks pretty good to me! Although I'm still not sure what's the benefit of setting the frame width/height, if you already "control" that with the quality parameter. For example, what would happen if the following options are used:
// change quality but use a fixed width/height ?
{quality: '480p', videoFrameWidth: 1280, videoFrameHeight: 960}
{quality: '720p', videoFrameWidth: 1280, videoFrameHeight: 960}
{quality: '1080p', videoFrameWidth: 1280, videoFrameHeight: 960}
// The other way around
{quality: '720p', videoFrameWidth: 1280, videoFrameHeight: 480}
{quality: '720p', videoFrameWidth: 1280, videoFrameHeight: 720}
{quality: '720p', videoFrameWidth: 1920, videoFrameHeight: 1080}
Looks like it may end up causing some confusion because the pixel dimension is usually strictly tied to the quality name.
Each quality maps to one of the CamcorderProfile (https://developer.android.com/reference/android/media/CamcorderProfile). A profile has a fixed set of settings like fps, bitrate, resolution, codec etc but you are still allowed to change them as per your requirement. The reason for these changes was that we needed to record video in 4:3 at a higher resolution (not just 480p). Most of all these profiles correspond to 16:9, for example: QUALITY_1080P gives you 1920x1080. If I want to record 1080p in 4:3 (i.e. 1440x1080), this PR allows to you do that.
{quality: '1080p', videoFrameWidth: 1440}
It means "Use 1080p profile but override the width to 1440.".
Quality represents a baseline profile and we need to allow flexibility to change specific attributes of that profile.
@makzee that greatly explains it, and makes complete sense. Good work!
Do we need this for iOS as well?
Thanks @cristianoccazinsp.
Yes we need this for iOS as well but I don't have a bandwidth for it right now. I'm planning to implement this in a month or so.
I see, I'm slightly confused, but when I set 4:3 I always get consistent videos in either 720p or 480p (with different aspect rations for each quality, basically 4:3 is ignored right now?). Is ratio='4:3' even used when recording videos? What would happen to iOS?
4:3
is actually 640:480
in iOS. Implementing this on iOS should be doable, AVCaptureMovieFileOutput settings include width and height keys, havent used/tested it myself though, they might be read-only. We should have in mind setting these outputsettings (including codecType) leads to the video being re-encoded as its recorded and might mean a performance hit as more settings are set.
(Note for v4): The options that make a difference between raw recording and re-encoding should be made clear even if they change across devices, mostly on Android. Remove 4:3