mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 14:55:37 +00:00
feat(export): add native aspect ratio option for background-free exports
This commit is contained in:
@@ -1156,9 +1156,10 @@ export default function VideoEditor() {
|
||||
videoPlaybackRef.current?.pause();
|
||||
}
|
||||
|
||||
const aspectRatioValue = getAspectRatioValue(aspectRatio);
|
||||
const sourceWidth = video.videoWidth || 1920;
|
||||
const sourceHeight = video.videoHeight || 1080;
|
||||
const sourceAspectRatio = sourceHeight > 0 ? sourceWidth / sourceHeight : 16 / 9;
|
||||
const aspectRatioValue = getAspectRatioValue(aspectRatio, sourceAspectRatio);
|
||||
|
||||
// Get preview CONTAINER dimensions for scaling
|
||||
const playbackRef = videoPlaybackRef.current;
|
||||
@@ -1241,7 +1242,10 @@ export default function VideoEditor() {
|
||||
exportWidth = sourceWidth;
|
||||
exportHeight = sourceHeight;
|
||||
|
||||
if (aspectRatioValue === 1) {
|
||||
if (aspectRatio === 'native') {
|
||||
exportWidth = Math.floor(sourceWidth / 2) * 2;
|
||||
exportHeight = Math.floor(sourceHeight / 2) * 2;
|
||||
} else if (aspectRatioValue === 1) {
|
||||
// Square (1:1): use smaller dimension to avoid codec limits
|
||||
const baseDimension = Math.floor(Math.min(sourceWidth, sourceHeight) / 2) * 2;
|
||||
exportWidth = baseDimension;
|
||||
@@ -1544,7 +1548,13 @@ export default function VideoEditor() {
|
||||
<div className="w-full h-full flex flex-col items-center justify-center bg-black/40 rounded-2xl border border-white/5 shadow-2xl overflow-hidden">
|
||||
{/* Video preview */}
|
||||
<div className="w-full flex justify-center items-center" style={{ flex: '1 1 auto', margin: '6px 0 0' }}>
|
||||
<div className="relative" style={{ width: 'auto', height: '100%', aspectRatio: getAspectRatioValue(aspectRatio), maxWidth: '100%', margin: '0 auto', boxSizing: 'border-box' }}>
|
||||
<div className="relative" style={{ width: 'auto', height: '100%', aspectRatio: getAspectRatioValue(aspectRatio, (() => {
|
||||
const previewVideo = videoPlaybackRef.current?.video;
|
||||
if (previewVideo && previewVideo.videoHeight > 0) {
|
||||
return previewVideo.videoWidth / previewVideo.videoHeight;
|
||||
}
|
||||
return 16 / 9;
|
||||
})()), maxWidth: '100%', margin: '0 auto', boxSizing: 'border-box' }}>
|
||||
<VideoPlayback
|
||||
key={videoPath || 'no-video'}
|
||||
aspectRatio={aspectRatio}
|
||||
|
||||
@@ -1029,8 +1029,20 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(({
|
||||
? { backgroundImage: `url(${resolvedWallpaper || ''})` }
|
||||
: { background: resolvedWallpaper || '' };
|
||||
|
||||
const nativeAspectRatio = (() => {
|
||||
const locked = lockedVideoDimensionsRef.current;
|
||||
if (locked && locked.height > 0) {
|
||||
return locked.width / locked.height;
|
||||
}
|
||||
const video = videoRef.current;
|
||||
if (video && video.videoHeight > 0) {
|
||||
return video.videoWidth / video.videoHeight;
|
||||
}
|
||||
return 16 / 9;
|
||||
})();
|
||||
|
||||
return (
|
||||
<div className="relative rounded-sm overflow-hidden" style={{ width: '100%', aspectRatio: formatAspectRatioForCSS(aspectRatio) }}>
|
||||
<div className="relative rounded-sm overflow-hidden" style={{ width: '100%', aspectRatio: formatAspectRatioForCSS(aspectRatio, nativeAspectRatio) }}>
|
||||
{/* Background layer - always render as DOM element with blur */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const ASPECT_RATIOS = ['16:9', '9:16', '1:1', '4:3', '4:5', '16:10', '10:16'] as const;
|
||||
export const ASPECT_RATIOS = ['native', '16:9', '9:16', '1:1', '4:3', '4:5', '16:10', '10:16'] as const;
|
||||
|
||||
export type AspectRatio = typeof ASPECT_RATIOS[number];
|
||||
|
||||
@@ -7,8 +7,9 @@ export type AspectRatio = typeof ASPECT_RATIOS[number];
|
||||
* Uses exhaustive type checking to ensure all AspectRatio cases are handled.
|
||||
* If TypeScript errors here, a new ratio was added to the type but not handled.
|
||||
*/
|
||||
export function getAspectRatioValue(aspectRatio: AspectRatio): number {
|
||||
export function getAspectRatioValue(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): number {
|
||||
switch (aspectRatio) {
|
||||
case 'native': return nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9;
|
||||
case '16:9': return 16 / 9;
|
||||
case '9:16': return 9 / 16;
|
||||
case '1:1': return 1;
|
||||
@@ -26,9 +27,10 @@ export function getAspectRatioValue(aspectRatio: AspectRatio): number {
|
||||
|
||||
export function getAspectRatioDimensions(
|
||||
aspectRatio: AspectRatio,
|
||||
baseWidth: number
|
||||
baseWidth: number,
|
||||
nativeAspectRatio?: number,
|
||||
): { width: number; height: number } {
|
||||
const ratio = getAspectRatioValue(aspectRatio);
|
||||
const ratio = getAspectRatioValue(aspectRatio, nativeAspectRatio);
|
||||
return {
|
||||
width: baseWidth,
|
||||
height: baseWidth / ratio,
|
||||
@@ -36,11 +38,17 @@ export function getAspectRatioDimensions(
|
||||
}
|
||||
|
||||
export function getAspectRatioLabel(aspectRatio: AspectRatio): string {
|
||||
if (aspectRatio === 'native') {
|
||||
return 'Native';
|
||||
}
|
||||
return aspectRatio;
|
||||
}
|
||||
|
||||
|
||||
export function formatAspectRatioForCSS(aspectRatio: AspectRatio): string {
|
||||
export function formatAspectRatioForCSS(aspectRatio: AspectRatio, nativeAspectRatio = 16 / 9): string {
|
||||
if (aspectRatio === 'native') {
|
||||
return `${nativeAspectRatio > 0 ? nativeAspectRatio : 16 / 9}`;
|
||||
}
|
||||
return aspectRatio.replace(':', '/');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user