ugcinc-render 1.5.31 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -782,6 +782,291 @@ interface EditorSegment {
782
782
  volume?: number;
783
783
  }
784
784
 
785
+ /**
786
+ * Video Deduplication Configuration
787
+ *
788
+ * Two ways to configure deduplication:
789
+ * 1. Use a preset level: 'level1' | 'level2' | 'level3' | 'level4' | 'level5'
790
+ * 2. Provide a custom DeduplicationConfig object
791
+ *
792
+ * @example
793
+ * // Using a preset level
794
+ * const dedup: DeduplicationInput = 'level3';
795
+ *
796
+ * @example
797
+ * // Using custom config
798
+ * const dedup: DeduplicationInput = {
799
+ * phone_config: { phone: 'iphone', phone_model: 'iphone', inject_exif: true },
800
+ * lens_correction: { k1: -0.05, k2: 0.01 },
801
+ * };
802
+ */
803
+ type DeduplicationLevel = 'level1' | 'level2' | 'level3' | 'level4' | 'level5';
804
+ type DeduplicationInput = DeduplicationLevel | DeduplicationConfig;
805
+ type PhoneType = 'iphone' | 'android';
806
+ type PhoneModel = 'iphone' | 'samsung' | 'pixel';
807
+ interface PhoneConfig {
808
+ /** Phone platform type */
809
+ phone: PhoneType;
810
+ /** Specific phone model to mimic */
811
+ phone_model: PhoneModel;
812
+ /** Inject EXIF metadata */
813
+ inject_exif: boolean;
814
+ /** Region code (e.g., "US") */
815
+ region?: string;
816
+ }
817
+ type VideoCodec = 'H264' | 'H265';
818
+ type VideoExtension = 'MP4' | 'MOV';
819
+ type Acceleration = 'nvidia' | 'cpu';
820
+ interface TraceRemovalConfig {
821
+ /** Output codec */
822
+ codec: VideoCodec;
823
+ /** Output container format (H265 should use MOV) */
824
+ video_extension: VideoExtension;
825
+ /** Hardware acceleration type */
826
+ acceleration?: Acceleration;
827
+ /** Remove FFmpeg signatures from binary */
828
+ remove_ffmpeg_signatures: boolean;
829
+ /** Remove encoder metadata */
830
+ remove_encoder_metadata: boolean;
831
+ }
832
+ interface MobileEncodingConfig {
833
+ /** Use GOP of 60 (typical for mobile cameras) */
834
+ use_gop: boolean;
835
+ /** Delete B-frames (typical for mobile) */
836
+ delete_b_frames: boolean;
837
+ /** Adjust keyframe intervals */
838
+ change_keyframes: boolean;
839
+ /** Change pixel format to mobile-typical */
840
+ change_pixel_format: boolean;
841
+ /** Use mobile color palette */
842
+ mobile_palette: boolean;
843
+ }
844
+ interface VisualAdjustmentsConfig {
845
+ /** Brightness adjustment range (random value within +-range) */
846
+ brightness?: number;
847
+ /** Gamma adjustment range */
848
+ gamma?: number;
849
+ /** Saturation adjustment range */
850
+ saturation?: number;
851
+ /** Contrast adjustment range */
852
+ contrast?: number;
853
+ /** Horizontal flip */
854
+ horizontal_flip?: boolean;
855
+ /** Rotation in degrees (clockwise) */
856
+ rotate_right?: number;
857
+ /** Rotation in degrees (counter-clockwise) */
858
+ rotate_left?: number;
859
+ }
860
+ interface CropConfig {
861
+ /** Pixels to crop from top */
862
+ crop_top?: number;
863
+ /** Pixels to crop from bottom */
864
+ crop_bottom?: number;
865
+ /** Pixels to crop from left */
866
+ crop_left?: number;
867
+ /** Pixels to crop from right */
868
+ crop_right?: number;
869
+ }
870
+ interface SpeedConfig {
871
+ /** Speed multiplier (e.g., 1.2 for 20% faster) */
872
+ speed_up?: number;
873
+ /** Slow down multiplier (e.g., 0.8 for 20% slower) */
874
+ slow_down?: number;
875
+ }
876
+ interface CuttingConfig {
877
+ /** Cut from beginning in milliseconds */
878
+ cut_begin_ms?: number;
879
+ /** Cut from end in milliseconds */
880
+ cut_end_ms?: number;
881
+ /** Cut from middle in milliseconds */
882
+ cut_middle_ms?: number;
883
+ }
884
+ interface LensCorrectionConfig {
885
+ /** Barrel/pincushion distortion coefficient (-0.1 to 0.1 typical) */
886
+ k1: number;
887
+ /** Secondary distortion coefficient */
888
+ k2: number;
889
+ }
890
+ interface ColorShiftConfig {
891
+ /** Enable dynamic color shifting over time */
892
+ enabled: boolean;
893
+ /** Opacity of the effect (0-100) */
894
+ color_shift_opacity?: number;
895
+ /** Speed of color shifting */
896
+ color_shift_speed?: number;
897
+ /** Custom hue expression (e.g., "sin(t)*4.0") */
898
+ hue_expression?: string;
899
+ /** Custom saturation expression (e.g., "1+sin(t)*0.2") */
900
+ saturation_expression?: string;
901
+ }
902
+ interface FrameManipulationConfig {
903
+ /** Skip random frames */
904
+ random_skip_frames?: boolean;
905
+ /** Temporal transition (WARNING: can desync audio) */
906
+ temporal_transition?: boolean;
907
+ /** Time warp effect (WARNING: can cause artifacts) */
908
+ time_warp?: boolean;
909
+ /** Temporal blend between frames */
910
+ tblend?: boolean;
911
+ /** RGBA channel shift */
912
+ rgba_shift?: boolean;
913
+ }
914
+ type BlendMode = 'overlay' | 'multiply' | 'screen';
915
+ interface GradientOverlayConfig {
916
+ /** Enable animated gradient overlay */
917
+ enabled: boolean;
918
+ /** Blend mode */
919
+ blend_mode?: BlendMode;
920
+ /** Opacity (0.01 to 0.1 typical) */
921
+ opacity?: number;
922
+ }
923
+ type DiagonalFilterType = 'hexagonal_grid' | 'diagonal_square_grid' | 'scan_lines' | 'scan_lines_green' | 'scan_lines_red' | 'scan_lines_blue';
924
+ interface DiagonalFilterConfig {
925
+ /** Enable diagonal/scanline filter */
926
+ enabled: boolean;
927
+ /** Filter type */
928
+ scan_line_filter: DiagonalFilterType;
929
+ }
930
+ interface ColorFilterConfig {
931
+ /** Vintage effect */
932
+ vintage?: boolean;
933
+ /** Black and white */
934
+ blackwhite?: boolean;
935
+ /** Sepia tone */
936
+ sepia?: boolean;
937
+ /** Blur effect */
938
+ blur?: boolean;
939
+ /** Sharpen effect */
940
+ sharpen?: boolean;
941
+ /** Pink overlay */
942
+ pink_overlay?: boolean;
943
+ /** Green color tint */
944
+ green_color?: boolean;
945
+ /** Red color tint */
946
+ red_color?: boolean;
947
+ /** Blue color tint */
948
+ blue_color?: boolean;
949
+ }
950
+ type EnhanceLevel = '2k' | '4k';
951
+ interface EnhancementConfig {
952
+ /** Upscale video using Lanczos + noise reduction */
953
+ enhance_video?: EnhanceLevel;
954
+ }
955
+ interface AudioConfig {
956
+ /** Mute all audio */
957
+ mute_audio?: boolean;
958
+ /** Apply random pitch shift */
959
+ random_pitch?: boolean;
960
+ /** Add white noise */
961
+ white_noise?: boolean;
962
+ }
963
+ interface GifSource {
964
+ /** URL to the GIF file */
965
+ url: string;
966
+ /** Enable this GIF */
967
+ enabled: boolean;
968
+ }
969
+ interface GifOverlayConfig {
970
+ /** Enable GIF overlay */
971
+ animated_gif: boolean;
972
+ /** Height of GIF strip in pixels */
973
+ height?: number;
974
+ /** Header GIF configuration */
975
+ header?: GifSource;
976
+ /** Footer GIF configuration */
977
+ footer?: GifSource;
978
+ }
979
+ interface ParticleOverlayConfig {
980
+ /** Enable particle overlay */
981
+ enabled: boolean;
982
+ /** Particle video URL or filename */
983
+ particle_file?: string;
984
+ /** Blend opacity */
985
+ opacity?: number;
986
+ }
987
+ interface DeduplicationConfig {
988
+ /** Phone metadata configuration */
989
+ phone_config?: PhoneConfig;
990
+ /** FFmpeg trace removal configuration */
991
+ trace_removal?: TraceRemovalConfig;
992
+ /** Mobile-typical encoding settings */
993
+ mobile_encoding?: MobileEncodingConfig;
994
+ /** Visual adjustments (brightness, contrast, etc.) */
995
+ visual_adjustments?: VisualAdjustmentsConfig;
996
+ /** Crop configuration */
997
+ crop?: CropConfig;
998
+ /** Speed adjustments */
999
+ speed?: SpeedConfig;
1000
+ /** Cutting/trimming */
1001
+ cutting?: CuttingConfig;
1002
+ /** Lens correction (critical for hash breaking) */
1003
+ lens_correction?: LensCorrectionConfig;
1004
+ /** Dynamic color shift (critical for hash breaking) */
1005
+ color_shift?: ColorShiftConfig;
1006
+ /** Frame manipulation */
1007
+ frame_manipulation?: FrameManipulationConfig;
1008
+ /** Animated gradient overlay */
1009
+ gradient_overlay?: GradientOverlayConfig;
1010
+ /** Diagonal/scanline filter */
1011
+ diagonal_filter?: DiagonalFilterConfig;
1012
+ /** Color filter presets */
1013
+ color_filter?: ColorFilterConfig;
1014
+ /** Video enhancement/upscaling */
1015
+ enhancement?: EnhancementConfig;
1016
+ /** Audio manipulation */
1017
+ audio?: AudioConfig;
1018
+ /** GIF overlay */
1019
+ gif_overlay?: GifOverlayConfig;
1020
+ /** Particle overlay */
1021
+ particle_overlay?: ParticleOverlayConfig;
1022
+ }
1023
+ /**
1024
+ * Level 1: Minimal
1025
+ * - Phone metadata injection only
1026
+ */
1027
+ declare const LEVEL_1_CONFIG: DeduplicationConfig;
1028
+ /**
1029
+ * Level 2: Basic
1030
+ * - Phone metadata
1031
+ * - FFmpeg trace removal
1032
+ */
1033
+ declare const LEVEL_2_CONFIG: DeduplicationConfig;
1034
+ /**
1035
+ * Level 3: Standard
1036
+ * - Phone metadata
1037
+ * - FFmpeg trace removal
1038
+ * - Mobile encoding settings
1039
+ * - Subtle visual adjustments
1040
+ */
1041
+ declare const LEVEL_3_CONFIG: DeduplicationConfig;
1042
+ /**
1043
+ * Level 4: Aggressive
1044
+ * - Everything in Level 3
1045
+ * - Lens correction (geometry distortion)
1046
+ * - Dynamic color shift
1047
+ * - Random frame skips
1048
+ */
1049
+ declare const LEVEL_4_CONFIG: DeduplicationConfig;
1050
+ /**
1051
+ * Level 5: Maximum
1052
+ * - All modifications enabled
1053
+ * - Strongest settings
1054
+ * - Audio muted (recommended for TikTok)
1055
+ */
1056
+ declare const LEVEL_5_CONFIG: DeduplicationConfig;
1057
+ /**
1058
+ * Map of level names to configs
1059
+ */
1060
+ declare const DEDUPLICATION_LEVELS: Record<DeduplicationLevel, DeduplicationConfig>;
1061
+ /**
1062
+ * Helper function to check if input is a level string
1063
+ */
1064
+ declare function isDeduplicationLevel(input: DeduplicationInput): input is DeduplicationLevel;
1065
+ /**
1066
+ * Helper function to resolve input to config
1067
+ */
1068
+ declare function resolveDeduplicationConfig(input: DeduplicationInput): DeduplicationConfig;
1069
+
785
1070
  interface ImageEditorCompositionProps {
786
1071
  /** The editor configuration to render (legacy format with pre-resolved segments) */
787
1072
  config?: ImageEditorConfig;
@@ -1365,4 +1650,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1365
1650
 
1366
1651
  declare const RenderRoot: React.FC;
1367
1652
 
1368
- export { APPLE_EMOJI_FONT, type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextStyleProperties, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, debugFontStatus, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
1653
+ export { APPLE_EMOJI_FONT, type Acceleration, type AudioConfig, type AudioSegment, type BaseEditorConfig, type BaseSegment, type BlendMode, type BorderRadiusConfig, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropAxisConfig, type CropBoundary, type CropBounds, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, DIMENSION_PRESETS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientOverlayConfig, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type SpeedConfig, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextStyleProperties, type TextWrap, type TimeMode, type TimeValue, type TraceRemovalConfig, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoCodec, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, debugFontStatus, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDeduplicationLevel, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveDeduplicationConfig, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
package/dist/index.d.ts CHANGED
@@ -782,6 +782,291 @@ interface EditorSegment {
782
782
  volume?: number;
783
783
  }
784
784
 
785
+ /**
786
+ * Video Deduplication Configuration
787
+ *
788
+ * Two ways to configure deduplication:
789
+ * 1. Use a preset level: 'level1' | 'level2' | 'level3' | 'level4' | 'level5'
790
+ * 2. Provide a custom DeduplicationConfig object
791
+ *
792
+ * @example
793
+ * // Using a preset level
794
+ * const dedup: DeduplicationInput = 'level3';
795
+ *
796
+ * @example
797
+ * // Using custom config
798
+ * const dedup: DeduplicationInput = {
799
+ * phone_config: { phone: 'iphone', phone_model: 'iphone', inject_exif: true },
800
+ * lens_correction: { k1: -0.05, k2: 0.01 },
801
+ * };
802
+ */
803
+ type DeduplicationLevel = 'level1' | 'level2' | 'level3' | 'level4' | 'level5';
804
+ type DeduplicationInput = DeduplicationLevel | DeduplicationConfig;
805
+ type PhoneType = 'iphone' | 'android';
806
+ type PhoneModel = 'iphone' | 'samsung' | 'pixel';
807
+ interface PhoneConfig {
808
+ /** Phone platform type */
809
+ phone: PhoneType;
810
+ /** Specific phone model to mimic */
811
+ phone_model: PhoneModel;
812
+ /** Inject EXIF metadata */
813
+ inject_exif: boolean;
814
+ /** Region code (e.g., "US") */
815
+ region?: string;
816
+ }
817
+ type VideoCodec = 'H264' | 'H265';
818
+ type VideoExtension = 'MP4' | 'MOV';
819
+ type Acceleration = 'nvidia' | 'cpu';
820
+ interface TraceRemovalConfig {
821
+ /** Output codec */
822
+ codec: VideoCodec;
823
+ /** Output container format (H265 should use MOV) */
824
+ video_extension: VideoExtension;
825
+ /** Hardware acceleration type */
826
+ acceleration?: Acceleration;
827
+ /** Remove FFmpeg signatures from binary */
828
+ remove_ffmpeg_signatures: boolean;
829
+ /** Remove encoder metadata */
830
+ remove_encoder_metadata: boolean;
831
+ }
832
+ interface MobileEncodingConfig {
833
+ /** Use GOP of 60 (typical for mobile cameras) */
834
+ use_gop: boolean;
835
+ /** Delete B-frames (typical for mobile) */
836
+ delete_b_frames: boolean;
837
+ /** Adjust keyframe intervals */
838
+ change_keyframes: boolean;
839
+ /** Change pixel format to mobile-typical */
840
+ change_pixel_format: boolean;
841
+ /** Use mobile color palette */
842
+ mobile_palette: boolean;
843
+ }
844
+ interface VisualAdjustmentsConfig {
845
+ /** Brightness adjustment range (random value within +-range) */
846
+ brightness?: number;
847
+ /** Gamma adjustment range */
848
+ gamma?: number;
849
+ /** Saturation adjustment range */
850
+ saturation?: number;
851
+ /** Contrast adjustment range */
852
+ contrast?: number;
853
+ /** Horizontal flip */
854
+ horizontal_flip?: boolean;
855
+ /** Rotation in degrees (clockwise) */
856
+ rotate_right?: number;
857
+ /** Rotation in degrees (counter-clockwise) */
858
+ rotate_left?: number;
859
+ }
860
+ interface CropConfig {
861
+ /** Pixels to crop from top */
862
+ crop_top?: number;
863
+ /** Pixels to crop from bottom */
864
+ crop_bottom?: number;
865
+ /** Pixels to crop from left */
866
+ crop_left?: number;
867
+ /** Pixels to crop from right */
868
+ crop_right?: number;
869
+ }
870
+ interface SpeedConfig {
871
+ /** Speed multiplier (e.g., 1.2 for 20% faster) */
872
+ speed_up?: number;
873
+ /** Slow down multiplier (e.g., 0.8 for 20% slower) */
874
+ slow_down?: number;
875
+ }
876
+ interface CuttingConfig {
877
+ /** Cut from beginning in milliseconds */
878
+ cut_begin_ms?: number;
879
+ /** Cut from end in milliseconds */
880
+ cut_end_ms?: number;
881
+ /** Cut from middle in milliseconds */
882
+ cut_middle_ms?: number;
883
+ }
884
+ interface LensCorrectionConfig {
885
+ /** Barrel/pincushion distortion coefficient (-0.1 to 0.1 typical) */
886
+ k1: number;
887
+ /** Secondary distortion coefficient */
888
+ k2: number;
889
+ }
890
+ interface ColorShiftConfig {
891
+ /** Enable dynamic color shifting over time */
892
+ enabled: boolean;
893
+ /** Opacity of the effect (0-100) */
894
+ color_shift_opacity?: number;
895
+ /** Speed of color shifting */
896
+ color_shift_speed?: number;
897
+ /** Custom hue expression (e.g., "sin(t)*4.0") */
898
+ hue_expression?: string;
899
+ /** Custom saturation expression (e.g., "1+sin(t)*0.2") */
900
+ saturation_expression?: string;
901
+ }
902
+ interface FrameManipulationConfig {
903
+ /** Skip random frames */
904
+ random_skip_frames?: boolean;
905
+ /** Temporal transition (WARNING: can desync audio) */
906
+ temporal_transition?: boolean;
907
+ /** Time warp effect (WARNING: can cause artifacts) */
908
+ time_warp?: boolean;
909
+ /** Temporal blend between frames */
910
+ tblend?: boolean;
911
+ /** RGBA channel shift */
912
+ rgba_shift?: boolean;
913
+ }
914
+ type BlendMode = 'overlay' | 'multiply' | 'screen';
915
+ interface GradientOverlayConfig {
916
+ /** Enable animated gradient overlay */
917
+ enabled: boolean;
918
+ /** Blend mode */
919
+ blend_mode?: BlendMode;
920
+ /** Opacity (0.01 to 0.1 typical) */
921
+ opacity?: number;
922
+ }
923
+ type DiagonalFilterType = 'hexagonal_grid' | 'diagonal_square_grid' | 'scan_lines' | 'scan_lines_green' | 'scan_lines_red' | 'scan_lines_blue';
924
+ interface DiagonalFilterConfig {
925
+ /** Enable diagonal/scanline filter */
926
+ enabled: boolean;
927
+ /** Filter type */
928
+ scan_line_filter: DiagonalFilterType;
929
+ }
930
+ interface ColorFilterConfig {
931
+ /** Vintage effect */
932
+ vintage?: boolean;
933
+ /** Black and white */
934
+ blackwhite?: boolean;
935
+ /** Sepia tone */
936
+ sepia?: boolean;
937
+ /** Blur effect */
938
+ blur?: boolean;
939
+ /** Sharpen effect */
940
+ sharpen?: boolean;
941
+ /** Pink overlay */
942
+ pink_overlay?: boolean;
943
+ /** Green color tint */
944
+ green_color?: boolean;
945
+ /** Red color tint */
946
+ red_color?: boolean;
947
+ /** Blue color tint */
948
+ blue_color?: boolean;
949
+ }
950
+ type EnhanceLevel = '2k' | '4k';
951
+ interface EnhancementConfig {
952
+ /** Upscale video using Lanczos + noise reduction */
953
+ enhance_video?: EnhanceLevel;
954
+ }
955
+ interface AudioConfig {
956
+ /** Mute all audio */
957
+ mute_audio?: boolean;
958
+ /** Apply random pitch shift */
959
+ random_pitch?: boolean;
960
+ /** Add white noise */
961
+ white_noise?: boolean;
962
+ }
963
+ interface GifSource {
964
+ /** URL to the GIF file */
965
+ url: string;
966
+ /** Enable this GIF */
967
+ enabled: boolean;
968
+ }
969
+ interface GifOverlayConfig {
970
+ /** Enable GIF overlay */
971
+ animated_gif: boolean;
972
+ /** Height of GIF strip in pixels */
973
+ height?: number;
974
+ /** Header GIF configuration */
975
+ header?: GifSource;
976
+ /** Footer GIF configuration */
977
+ footer?: GifSource;
978
+ }
979
+ interface ParticleOverlayConfig {
980
+ /** Enable particle overlay */
981
+ enabled: boolean;
982
+ /** Particle video URL or filename */
983
+ particle_file?: string;
984
+ /** Blend opacity */
985
+ opacity?: number;
986
+ }
987
+ interface DeduplicationConfig {
988
+ /** Phone metadata configuration */
989
+ phone_config?: PhoneConfig;
990
+ /** FFmpeg trace removal configuration */
991
+ trace_removal?: TraceRemovalConfig;
992
+ /** Mobile-typical encoding settings */
993
+ mobile_encoding?: MobileEncodingConfig;
994
+ /** Visual adjustments (brightness, contrast, etc.) */
995
+ visual_adjustments?: VisualAdjustmentsConfig;
996
+ /** Crop configuration */
997
+ crop?: CropConfig;
998
+ /** Speed adjustments */
999
+ speed?: SpeedConfig;
1000
+ /** Cutting/trimming */
1001
+ cutting?: CuttingConfig;
1002
+ /** Lens correction (critical for hash breaking) */
1003
+ lens_correction?: LensCorrectionConfig;
1004
+ /** Dynamic color shift (critical for hash breaking) */
1005
+ color_shift?: ColorShiftConfig;
1006
+ /** Frame manipulation */
1007
+ frame_manipulation?: FrameManipulationConfig;
1008
+ /** Animated gradient overlay */
1009
+ gradient_overlay?: GradientOverlayConfig;
1010
+ /** Diagonal/scanline filter */
1011
+ diagonal_filter?: DiagonalFilterConfig;
1012
+ /** Color filter presets */
1013
+ color_filter?: ColorFilterConfig;
1014
+ /** Video enhancement/upscaling */
1015
+ enhancement?: EnhancementConfig;
1016
+ /** Audio manipulation */
1017
+ audio?: AudioConfig;
1018
+ /** GIF overlay */
1019
+ gif_overlay?: GifOverlayConfig;
1020
+ /** Particle overlay */
1021
+ particle_overlay?: ParticleOverlayConfig;
1022
+ }
1023
+ /**
1024
+ * Level 1: Minimal
1025
+ * - Phone metadata injection only
1026
+ */
1027
+ declare const LEVEL_1_CONFIG: DeduplicationConfig;
1028
+ /**
1029
+ * Level 2: Basic
1030
+ * - Phone metadata
1031
+ * - FFmpeg trace removal
1032
+ */
1033
+ declare const LEVEL_2_CONFIG: DeduplicationConfig;
1034
+ /**
1035
+ * Level 3: Standard
1036
+ * - Phone metadata
1037
+ * - FFmpeg trace removal
1038
+ * - Mobile encoding settings
1039
+ * - Subtle visual adjustments
1040
+ */
1041
+ declare const LEVEL_3_CONFIG: DeduplicationConfig;
1042
+ /**
1043
+ * Level 4: Aggressive
1044
+ * - Everything in Level 3
1045
+ * - Lens correction (geometry distortion)
1046
+ * - Dynamic color shift
1047
+ * - Random frame skips
1048
+ */
1049
+ declare const LEVEL_4_CONFIG: DeduplicationConfig;
1050
+ /**
1051
+ * Level 5: Maximum
1052
+ * - All modifications enabled
1053
+ * - Strongest settings
1054
+ * - Audio muted (recommended for TikTok)
1055
+ */
1056
+ declare const LEVEL_5_CONFIG: DeduplicationConfig;
1057
+ /**
1058
+ * Map of level names to configs
1059
+ */
1060
+ declare const DEDUPLICATION_LEVELS: Record<DeduplicationLevel, DeduplicationConfig>;
1061
+ /**
1062
+ * Helper function to check if input is a level string
1063
+ */
1064
+ declare function isDeduplicationLevel(input: DeduplicationInput): input is DeduplicationLevel;
1065
+ /**
1066
+ * Helper function to resolve input to config
1067
+ */
1068
+ declare function resolveDeduplicationConfig(input: DeduplicationInput): DeduplicationConfig;
1069
+
785
1070
  interface ImageEditorCompositionProps {
786
1071
  /** The editor configuration to render (legacy format with pre-resolved segments) */
787
1072
  config?: ImageEditorConfig;
@@ -1365,4 +1650,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1365
1650
 
1366
1651
  declare const RenderRoot: React.FC;
1367
1652
 
1368
- export { APPLE_EMOJI_FONT, type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextStyleProperties, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, debugFontStatus, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
1653
+ export { APPLE_EMOJI_FONT, type Acceleration, type AudioConfig, type AudioSegment, type BaseEditorConfig, type BaseSegment, type BlendMode, type BorderRadiusConfig, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropAxisConfig, type CropBoundary, type CropBounds, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, DIMENSION_PRESETS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientOverlayConfig, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type SpeedConfig, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextStyleProperties, type TextWrap, type TimeMode, type TimeValue, type TraceRemovalConfig, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoCodec, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, debugFontStatus, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDeduplicationLevel, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveDeduplicationConfig, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
package/dist/index.js CHANGED
@@ -31,12 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  APPLE_EMOJI_FONT: () => APPLE_EMOJI_FONT,
34
+ DEDUPLICATION_LEVELS: () => DEDUPLICATION_LEVELS,
34
35
  DIMENSION_PRESETS: () => DIMENSION_PRESETS,
35
36
  FONT_FAMILIES: () => FONT_FAMILIES,
36
37
  FONT_URLS: () => FONT_URLS,
37
38
  IMAGE_DEFAULTS: () => IMAGE_DEFAULTS,
38
39
  ImageEditorComposition: () => ImageEditorComposition,
39
40
  ImageElement: () => ImageElement,
41
+ LEVEL_1_CONFIG: () => LEVEL_1_CONFIG,
42
+ LEVEL_2_CONFIG: () => LEVEL_2_CONFIG,
43
+ LEVEL_3_CONFIG: () => LEVEL_3_CONFIG,
44
+ LEVEL_4_CONFIG: () => LEVEL_4_CONFIG,
45
+ LEVEL_5_CONFIG: () => LEVEL_5_CONFIG,
40
46
  RenderRoot: () => RenderRoot,
41
47
  TEXT_DEFAULTS: () => TEXT_DEFAULTS,
42
48
  TextElement: () => TextElement,
@@ -70,11 +76,13 @@ __export(index_exports, {
70
76
  getReferenceElementY: () => getReferenceElementY,
71
77
  getSegmentTimelinePosition: () => getSegmentTimelinePosition,
72
78
  hexToRgba: () => hexToRgba,
79
+ isDeduplicationLevel: () => isDeduplicationLevel,
73
80
  isDynamicCropEnabled: () => isDynamicCropEnabled,
74
81
  isSegmentVisibleAtTime: () => isSegmentVisibleAtTime,
75
82
  parseHexColor: () => parseHexColor,
76
83
  parseTime: () => parseTime,
77
84
  preloadFonts: () => preloadFonts,
85
+ resolveDeduplicationConfig: () => resolveDeduplicationConfig,
78
86
  resolveElementPositions: () => resolveElementPositions,
79
87
  useFontsLoaded: () => useFontsLoaded,
80
88
  useImageLoader: () => useImageLoader,
@@ -93,6 +101,184 @@ var DIMENSION_PRESETS = {
93
101
  "twitter": { width: 1200, height: 675, label: "Twitter/X (1200\xD7675)", ratio: "16:9" }
94
102
  };
95
103
 
104
+ // src/types/deduplication.ts
105
+ var LEVEL_1_CONFIG = {
106
+ phone_config: {
107
+ phone: "iphone",
108
+ phone_model: "iphone",
109
+ inject_exif: true,
110
+ region: "US"
111
+ }
112
+ };
113
+ var LEVEL_2_CONFIG = {
114
+ phone_config: {
115
+ phone: "iphone",
116
+ phone_model: "iphone",
117
+ inject_exif: true,
118
+ region: "US"
119
+ },
120
+ trace_removal: {
121
+ codec: "H265",
122
+ video_extension: "MOV",
123
+ acceleration: "nvidia",
124
+ remove_ffmpeg_signatures: true,
125
+ remove_encoder_metadata: true
126
+ }
127
+ };
128
+ var LEVEL_3_CONFIG = {
129
+ phone_config: {
130
+ phone: "iphone",
131
+ phone_model: "iphone",
132
+ inject_exif: true,
133
+ region: "US"
134
+ },
135
+ trace_removal: {
136
+ codec: "H265",
137
+ video_extension: "MOV",
138
+ acceleration: "nvidia",
139
+ remove_ffmpeg_signatures: true,
140
+ remove_encoder_metadata: true
141
+ },
142
+ mobile_encoding: {
143
+ use_gop: true,
144
+ delete_b_frames: false,
145
+ change_keyframes: true,
146
+ change_pixel_format: true,
147
+ mobile_palette: false
148
+ },
149
+ visual_adjustments: {
150
+ brightness: 5,
151
+ contrast: 3,
152
+ saturation: 3
153
+ },
154
+ cutting: {
155
+ cut_begin_ms: 100,
156
+ cut_end_ms: 100
157
+ }
158
+ };
159
+ var LEVEL_4_CONFIG = {
160
+ phone_config: {
161
+ phone: "iphone",
162
+ phone_model: "iphone",
163
+ inject_exif: true,
164
+ region: "US"
165
+ },
166
+ trace_removal: {
167
+ codec: "H265",
168
+ video_extension: "MOV",
169
+ acceleration: "nvidia",
170
+ remove_ffmpeg_signatures: true,
171
+ remove_encoder_metadata: true
172
+ },
173
+ mobile_encoding: {
174
+ use_gop: true,
175
+ delete_b_frames: true,
176
+ change_keyframes: true,
177
+ change_pixel_format: true,
178
+ mobile_palette: false
179
+ },
180
+ visual_adjustments: {
181
+ brightness: 8,
182
+ contrast: 5,
183
+ saturation: 5,
184
+ horizontal_flip: true
185
+ },
186
+ cutting: {
187
+ cut_begin_ms: 200,
188
+ cut_end_ms: 100
189
+ },
190
+ lens_correction: {
191
+ k1: -0.03,
192
+ k2: 0.01
193
+ },
194
+ color_shift: {
195
+ enabled: true,
196
+ color_shift_opacity: 30,
197
+ color_shift_speed: 1
198
+ },
199
+ frame_manipulation: {
200
+ random_skip_frames: true
201
+ }
202
+ };
203
+ var LEVEL_5_CONFIG = {
204
+ phone_config: {
205
+ phone: "iphone",
206
+ phone_model: "iphone",
207
+ inject_exif: true,
208
+ region: "US"
209
+ },
210
+ trace_removal: {
211
+ codec: "H265",
212
+ video_extension: "MOV",
213
+ acceleration: "nvidia",
214
+ remove_ffmpeg_signatures: true,
215
+ remove_encoder_metadata: true
216
+ },
217
+ mobile_encoding: {
218
+ use_gop: true,
219
+ delete_b_frames: true,
220
+ change_keyframes: true,
221
+ change_pixel_format: true,
222
+ mobile_palette: true
223
+ },
224
+ visual_adjustments: {
225
+ brightness: 10,
226
+ contrast: 5,
227
+ saturation: 5,
228
+ gamma: 5,
229
+ horizontal_flip: true,
230
+ rotate_right: 0.5
231
+ },
232
+ cutting: {
233
+ cut_begin_ms: 512,
234
+ cut_end_ms: 100,
235
+ cut_middle_ms: 200
236
+ },
237
+ speed: {
238
+ speed_up: 1.02
239
+ },
240
+ lens_correction: {
241
+ k1: -0.05,
242
+ k2: 0.01
243
+ },
244
+ color_shift: {
245
+ enabled: true,
246
+ color_shift_opacity: 50,
247
+ color_shift_speed: 1,
248
+ hue_expression: "sin(t)*4.0",
249
+ saturation_expression: "1+sin(t)*0.2"
250
+ },
251
+ frame_manipulation: {
252
+ random_skip_frames: true,
253
+ tblend: false,
254
+ temporal_transition: false
255
+ },
256
+ gradient_overlay: {
257
+ enabled: true,
258
+ blend_mode: "overlay",
259
+ opacity: 0.05
260
+ },
261
+ audio: {
262
+ mute_audio: true
263
+ }
264
+ };
265
+ var DEDUPLICATION_LEVELS = {
266
+ level1: LEVEL_1_CONFIG,
267
+ level2: LEVEL_2_CONFIG,
268
+ level3: LEVEL_3_CONFIG,
269
+ level4: LEVEL_4_CONFIG,
270
+ level5: LEVEL_5_CONFIG
271
+ };
272
+ function isDeduplicationLevel(input) {
273
+ return typeof input === "string" && input in DEDUPLICATION_LEVELS;
274
+ }
275
+ function resolveDeduplicationConfig(input) {
276
+ if (isDeduplicationLevel(input)) {
277
+ return DEDUPLICATION_LEVELS[input];
278
+ }
279
+ return input;
280
+ }
281
+
96
282
  // src/compositions/ImageEditorComposition.tsx
97
283
  var import_react3 = require("react");
98
284
  var import_remotion2 = require("remotion");
@@ -1604,11 +1790,11 @@ function BackgroundImage({
1604
1790
  }
1605
1791
 
1606
1792
  // src/compositions/VideoEditorComposition.tsx
1607
- var import_react5 = __toESM(require("react"));
1793
+ var import_react5 = require("react");
1608
1794
  var import_remotion4 = require("remotion");
1609
1795
 
1610
1796
  // src/components/VideoElement.tsx
1611
- var import_react4 = __toESM(require("react"));
1797
+ var import_react4 = require("react");
1612
1798
  var import_remotion3 = require("remotion");
1613
1799
  var import_jsx_runtime4 = require("react/jsx-runtime");
1614
1800
  function fitModeToCss2(fit) {
@@ -1623,17 +1809,6 @@ function VideoElement({
1623
1809
  }) {
1624
1810
  const frame = (0, import_remotion3.useCurrentFrame)();
1625
1811
  const { fps } = (0, import_remotion3.useVideoConfig)();
1626
- import_react4.default.useEffect(() => {
1627
- console.log(`[VideoElement] Rendering segment ${segment.id}:`, {
1628
- src,
1629
- startFrame,
1630
- durationInFrames,
1631
- width: segment.width,
1632
- height: segment.height,
1633
- fit: segment.fit,
1634
- startTrim: segment.startTrim
1635
- });
1636
- }, [segment, src, startFrame, durationInFrames]);
1637
1812
  const fit = segment.fit ?? VIDEO_DEFAULTS.fit;
1638
1813
  const speed = segment.speed ?? VIDEO_DEFAULTS.speed;
1639
1814
  const volume = (segment.volume ?? VIDEO_DEFAULTS.volume) / 100;
@@ -1756,21 +1931,6 @@ function VideoEditorComposition({
1756
1931
  }) {
1757
1932
  const frame = (0, import_remotion4.useCurrentFrame)();
1758
1933
  const { fps, durationInFrames } = (0, import_remotion4.useVideoConfig)();
1759
- import_react5.default.useEffect(() => {
1760
- console.log("[VideoEditorComposition] Mounted with:", {
1761
- configChannels: config.channels.length,
1762
- sources,
1763
- textContent,
1764
- fps,
1765
- durationInFrames,
1766
- segments: config.channels.flatMap((c) => c.segments.map((s) => ({
1767
- id: s.id,
1768
- type: s.type,
1769
- source: s.source,
1770
- inputRef: s.inputRef
1771
- })))
1772
- });
1773
- }, [config, sources, textContent, fps, durationInFrames]);
1774
1934
  const segmentTimings = (0, import_react5.useMemo)(
1775
1935
  () => calculateSegmentTimings(config, fps),
1776
1936
  [config, fps]
@@ -1829,13 +1989,7 @@ function VideoEditorComposition({
1829
1989
  }
1830
1990
  if (segment.type === "image") {
1831
1991
  const src = getSource(segment);
1832
- console.log(`[VideoEditorComposition] Image segment ${segment.id}:`, {
1833
- inputRef: segment.inputRef,
1834
- src,
1835
- hasSource: !!src
1836
- });
1837
1992
  if (!src) {
1838
- console.warn(`No source found for image segment: ${segment.id}`);
1839
1993
  return null;
1840
1994
  }
1841
1995
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -1851,13 +2005,7 @@ function VideoEditorComposition({
1851
2005
  }
1852
2006
  if (segment.type === "video") {
1853
2007
  const src = getSource(segment);
1854
- console.log(`[VideoEditorComposition] Video segment ${segment.id}:`, {
1855
- inputRef: segment.inputRef,
1856
- src,
1857
- hasSource: !!src
1858
- });
1859
2008
  if (!src) {
1860
- console.warn(`No source found for video segment: ${segment.id}`);
1861
2009
  return null;
1862
2010
  }
1863
2011
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -2244,12 +2392,18 @@ var RenderRoot = () => {
2244
2392
  // Annotate the CommonJS export names for ESM import in node:
2245
2393
  0 && (module.exports = {
2246
2394
  APPLE_EMOJI_FONT,
2395
+ DEDUPLICATION_LEVELS,
2247
2396
  DIMENSION_PRESETS,
2248
2397
  FONT_FAMILIES,
2249
2398
  FONT_URLS,
2250
2399
  IMAGE_DEFAULTS,
2251
2400
  ImageEditorComposition,
2252
2401
  ImageElement,
2402
+ LEVEL_1_CONFIG,
2403
+ LEVEL_2_CONFIG,
2404
+ LEVEL_3_CONFIG,
2405
+ LEVEL_4_CONFIG,
2406
+ LEVEL_5_CONFIG,
2253
2407
  RenderRoot,
2254
2408
  TEXT_DEFAULTS,
2255
2409
  TextElement,
@@ -2283,11 +2437,13 @@ var RenderRoot = () => {
2283
2437
  getReferenceElementY,
2284
2438
  getSegmentTimelinePosition,
2285
2439
  hexToRgba,
2440
+ isDeduplicationLevel,
2286
2441
  isDynamicCropEnabled,
2287
2442
  isSegmentVisibleAtTime,
2288
2443
  parseHexColor,
2289
2444
  parseTime,
2290
2445
  preloadFonts,
2446
+ resolveDeduplicationConfig,
2291
2447
  resolveElementPositions,
2292
2448
  useFontsLoaded,
2293
2449
  useImageLoader,
package/dist/index.mjs CHANGED
@@ -7,6 +7,184 @@ var DIMENSION_PRESETS = {
7
7
  "twitter": { width: 1200, height: 675, label: "Twitter/X (1200\xD7675)", ratio: "16:9" }
8
8
  };
9
9
 
10
+ // src/types/deduplication.ts
11
+ var LEVEL_1_CONFIG = {
12
+ phone_config: {
13
+ phone: "iphone",
14
+ phone_model: "iphone",
15
+ inject_exif: true,
16
+ region: "US"
17
+ }
18
+ };
19
+ var LEVEL_2_CONFIG = {
20
+ phone_config: {
21
+ phone: "iphone",
22
+ phone_model: "iphone",
23
+ inject_exif: true,
24
+ region: "US"
25
+ },
26
+ trace_removal: {
27
+ codec: "H265",
28
+ video_extension: "MOV",
29
+ acceleration: "nvidia",
30
+ remove_ffmpeg_signatures: true,
31
+ remove_encoder_metadata: true
32
+ }
33
+ };
34
+ var LEVEL_3_CONFIG = {
35
+ phone_config: {
36
+ phone: "iphone",
37
+ phone_model: "iphone",
38
+ inject_exif: true,
39
+ region: "US"
40
+ },
41
+ trace_removal: {
42
+ codec: "H265",
43
+ video_extension: "MOV",
44
+ acceleration: "nvidia",
45
+ remove_ffmpeg_signatures: true,
46
+ remove_encoder_metadata: true
47
+ },
48
+ mobile_encoding: {
49
+ use_gop: true,
50
+ delete_b_frames: false,
51
+ change_keyframes: true,
52
+ change_pixel_format: true,
53
+ mobile_palette: false
54
+ },
55
+ visual_adjustments: {
56
+ brightness: 5,
57
+ contrast: 3,
58
+ saturation: 3
59
+ },
60
+ cutting: {
61
+ cut_begin_ms: 100,
62
+ cut_end_ms: 100
63
+ }
64
+ };
65
+ var LEVEL_4_CONFIG = {
66
+ phone_config: {
67
+ phone: "iphone",
68
+ phone_model: "iphone",
69
+ inject_exif: true,
70
+ region: "US"
71
+ },
72
+ trace_removal: {
73
+ codec: "H265",
74
+ video_extension: "MOV",
75
+ acceleration: "nvidia",
76
+ remove_ffmpeg_signatures: true,
77
+ remove_encoder_metadata: true
78
+ },
79
+ mobile_encoding: {
80
+ use_gop: true,
81
+ delete_b_frames: true,
82
+ change_keyframes: true,
83
+ change_pixel_format: true,
84
+ mobile_palette: false
85
+ },
86
+ visual_adjustments: {
87
+ brightness: 8,
88
+ contrast: 5,
89
+ saturation: 5,
90
+ horizontal_flip: true
91
+ },
92
+ cutting: {
93
+ cut_begin_ms: 200,
94
+ cut_end_ms: 100
95
+ },
96
+ lens_correction: {
97
+ k1: -0.03,
98
+ k2: 0.01
99
+ },
100
+ color_shift: {
101
+ enabled: true,
102
+ color_shift_opacity: 30,
103
+ color_shift_speed: 1
104
+ },
105
+ frame_manipulation: {
106
+ random_skip_frames: true
107
+ }
108
+ };
109
+ var LEVEL_5_CONFIG = {
110
+ phone_config: {
111
+ phone: "iphone",
112
+ phone_model: "iphone",
113
+ inject_exif: true,
114
+ region: "US"
115
+ },
116
+ trace_removal: {
117
+ codec: "H265",
118
+ video_extension: "MOV",
119
+ acceleration: "nvidia",
120
+ remove_ffmpeg_signatures: true,
121
+ remove_encoder_metadata: true
122
+ },
123
+ mobile_encoding: {
124
+ use_gop: true,
125
+ delete_b_frames: true,
126
+ change_keyframes: true,
127
+ change_pixel_format: true,
128
+ mobile_palette: true
129
+ },
130
+ visual_adjustments: {
131
+ brightness: 10,
132
+ contrast: 5,
133
+ saturation: 5,
134
+ gamma: 5,
135
+ horizontal_flip: true,
136
+ rotate_right: 0.5
137
+ },
138
+ cutting: {
139
+ cut_begin_ms: 512,
140
+ cut_end_ms: 100,
141
+ cut_middle_ms: 200
142
+ },
143
+ speed: {
144
+ speed_up: 1.02
145
+ },
146
+ lens_correction: {
147
+ k1: -0.05,
148
+ k2: 0.01
149
+ },
150
+ color_shift: {
151
+ enabled: true,
152
+ color_shift_opacity: 50,
153
+ color_shift_speed: 1,
154
+ hue_expression: "sin(t)*4.0",
155
+ saturation_expression: "1+sin(t)*0.2"
156
+ },
157
+ frame_manipulation: {
158
+ random_skip_frames: true,
159
+ tblend: false,
160
+ temporal_transition: false
161
+ },
162
+ gradient_overlay: {
163
+ enabled: true,
164
+ blend_mode: "overlay",
165
+ opacity: 0.05
166
+ },
167
+ audio: {
168
+ mute_audio: true
169
+ }
170
+ };
171
+ var DEDUPLICATION_LEVELS = {
172
+ level1: LEVEL_1_CONFIG,
173
+ level2: LEVEL_2_CONFIG,
174
+ level3: LEVEL_3_CONFIG,
175
+ level4: LEVEL_4_CONFIG,
176
+ level5: LEVEL_5_CONFIG
177
+ };
178
+ function isDeduplicationLevel(input) {
179
+ return typeof input === "string" && input in DEDUPLICATION_LEVELS;
180
+ }
181
+ function resolveDeduplicationConfig(input) {
182
+ if (isDeduplicationLevel(input)) {
183
+ return DEDUPLICATION_LEVELS[input];
184
+ }
185
+ return input;
186
+ }
187
+
10
188
  // src/compositions/ImageEditorComposition.tsx
11
189
  import { useMemo as useMemo3, useState, useEffect } from "react";
12
190
  import { AbsoluteFill, Img as Img2, delayRender, continueRender } from "remotion";
@@ -1518,11 +1696,11 @@ function BackgroundImage({
1518
1696
  }
1519
1697
 
1520
1698
  // src/compositions/VideoEditorComposition.tsx
1521
- import React5, { useMemo as useMemo5 } from "react";
1699
+ import { useMemo as useMemo5 } from "react";
1522
1700
  import { AbsoluteFill as AbsoluteFill2, useCurrentFrame as useCurrentFrame3, useVideoConfig as useVideoConfig3, Sequence, Audio } from "remotion";
1523
1701
 
1524
1702
  // src/components/VideoElement.tsx
1525
- import React4, { useMemo as useMemo4 } from "react";
1703
+ import { useMemo as useMemo4 } from "react";
1526
1704
  import { OffthreadVideo, useCurrentFrame as useCurrentFrame2, useVideoConfig as useVideoConfig2 } from "remotion";
1527
1705
  import { jsx as jsx4 } from "react/jsx-runtime";
1528
1706
  function fitModeToCss2(fit) {
@@ -1537,17 +1715,6 @@ function VideoElement({
1537
1715
  }) {
1538
1716
  const frame = useCurrentFrame2();
1539
1717
  const { fps } = useVideoConfig2();
1540
- React4.useEffect(() => {
1541
- console.log(`[VideoElement] Rendering segment ${segment.id}:`, {
1542
- src,
1543
- startFrame,
1544
- durationInFrames,
1545
- width: segment.width,
1546
- height: segment.height,
1547
- fit: segment.fit,
1548
- startTrim: segment.startTrim
1549
- });
1550
- }, [segment, src, startFrame, durationInFrames]);
1551
1718
  const fit = segment.fit ?? VIDEO_DEFAULTS.fit;
1552
1719
  const speed = segment.speed ?? VIDEO_DEFAULTS.speed;
1553
1720
  const volume = (segment.volume ?? VIDEO_DEFAULTS.volume) / 100;
@@ -1670,21 +1837,6 @@ function VideoEditorComposition({
1670
1837
  }) {
1671
1838
  const frame = useCurrentFrame3();
1672
1839
  const { fps, durationInFrames } = useVideoConfig3();
1673
- React5.useEffect(() => {
1674
- console.log("[VideoEditorComposition] Mounted with:", {
1675
- configChannels: config.channels.length,
1676
- sources,
1677
- textContent,
1678
- fps,
1679
- durationInFrames,
1680
- segments: config.channels.flatMap((c) => c.segments.map((s) => ({
1681
- id: s.id,
1682
- type: s.type,
1683
- source: s.source,
1684
- inputRef: s.inputRef
1685
- })))
1686
- });
1687
- }, [config, sources, textContent, fps, durationInFrames]);
1688
1840
  const segmentTimings = useMemo5(
1689
1841
  () => calculateSegmentTimings(config, fps),
1690
1842
  [config, fps]
@@ -1743,13 +1895,7 @@ function VideoEditorComposition({
1743
1895
  }
1744
1896
  if (segment.type === "image") {
1745
1897
  const src = getSource(segment);
1746
- console.log(`[VideoEditorComposition] Image segment ${segment.id}:`, {
1747
- inputRef: segment.inputRef,
1748
- src,
1749
- hasSource: !!src
1750
- });
1751
1898
  if (!src) {
1752
- console.warn(`No source found for image segment: ${segment.id}`);
1753
1899
  return null;
1754
1900
  }
1755
1901
  return /* @__PURE__ */ jsx5(
@@ -1765,13 +1911,7 @@ function VideoEditorComposition({
1765
1911
  }
1766
1912
  if (segment.type === "video") {
1767
1913
  const src = getSource(segment);
1768
- console.log(`[VideoEditorComposition] Video segment ${segment.id}:`, {
1769
- inputRef: segment.inputRef,
1770
- src,
1771
- hasSource: !!src
1772
- });
1773
1914
  if (!src) {
1774
- console.warn(`No source found for video segment: ${segment.id}`);
1775
1915
  return null;
1776
1916
  }
1777
1917
  return /* @__PURE__ */ jsx5(
@@ -2157,12 +2297,18 @@ var RenderRoot = () => {
2157
2297
  };
2158
2298
  export {
2159
2299
  APPLE_EMOJI_FONT,
2300
+ DEDUPLICATION_LEVELS,
2160
2301
  DIMENSION_PRESETS,
2161
2302
  FONT_FAMILIES,
2162
2303
  FONT_URLS,
2163
2304
  IMAGE_DEFAULTS,
2164
2305
  ImageEditorComposition,
2165
2306
  ImageElement,
2307
+ LEVEL_1_CONFIG,
2308
+ LEVEL_2_CONFIG,
2309
+ LEVEL_3_CONFIG,
2310
+ LEVEL_4_CONFIG,
2311
+ LEVEL_5_CONFIG,
2166
2312
  RenderRoot,
2167
2313
  TEXT_DEFAULTS,
2168
2314
  TextElement,
@@ -2196,11 +2342,13 @@ export {
2196
2342
  getReferenceElementY,
2197
2343
  getSegmentTimelinePosition,
2198
2344
  hexToRgba,
2345
+ isDeduplicationLevel,
2199
2346
  isDynamicCropEnabled,
2200
2347
  isSegmentVisibleAtTime,
2201
2348
  parseHexColor,
2202
2349
  parseTime,
2203
2350
  preloadFonts,
2351
+ resolveDeduplicationConfig,
2204
2352
  resolveElementPositions,
2205
2353
  useFontsLoaded,
2206
2354
  useImageLoader,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.5.31",
3
+ "version": "1.6.0",
4
4
  "description": "Unified rendering package for UGC Inc - shared types, components, and compositions for pixel-perfect client/server rendering",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",