diff --git a/src/index.tsx b/src/index.tsx
index b9ba13b..bdac106 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -23,6 +23,7 @@ import {
   type DimensionValue,
   Image,
   type ImageStyle,
+  Animated,
 } from 'react-native';
 import Video, {
   ResizeMode,
@@ -89,6 +90,7 @@ interface VideoPlayerComponentProps extends ReactVideoProps {
   onShowControls?: () => void;
   onMutePress?: (isMuted: boolean) => void;
   showDuration?: boolean;
+  animationDuration?: number;
 }
 
 const getDurationTime = (duration: number): string => {
@@ -151,6 +153,7 @@ const VideoPlayerComponent = forwardRef(
       onShowControls,
       onMutePress,
       showDuration = false,
+      animationDuration = 100,
     } = props;
 
     const [isStarted, setIsStarted] = useState(autoplay);
@@ -171,6 +174,13 @@ const VideoPlayerComponent = forwardRef(
     const seekProgressStart = useRef<number>(0);
     const wasPlayingBeforeSeek = useRef<boolean>(autoplay);
 
+    const animationValue = useRef(new Animated.Value(0)).current;
+
+    const controlsTranslateY = animationValue.interpolate({
+      inputRange: [0, 1],
+      outputRange: [48, 0],
+    });
+
     const getSizeStyles = useCallback(() => {
       const ratio = videoHeight / videoWidth;
       return { height: width * ratio, width: width };
@@ -197,18 +207,45 @@ const VideoPlayerComponent = forwardRef(
 
     const _hideControls = useCallback(() => {
       if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);
+
       controlsTimeoutRef.current = setTimeout(() => {
         if (onHideControls) onHideControls();
         if (disableControlsAutoHide) return;
-        setIsControlsVisible(false);
+
+        Animated.timing(animationValue, {
+          toValue: 0.1,
+          duration: animationDuration,
+          useNativeDriver: true,
+        }).start(() => {
+          setIsControlsVisible(false);
+        });
       }, controlsTimeout);
-    }, [onHideControls, disableControlsAutoHide, controlsTimeout]);
+    }, [
+      controlsTimeout,
+      onHideControls,
+      disableControlsAutoHide,
+      animationValue,
+      animationDuration,
+    ]);
 
     const _showControls = useCallback(() => {
       if (onShowControls && !isControlsVisible) onShowControls();
       setIsControlsVisible(true);
+
+      Animated.timing(animationValue, {
+        toValue: 1,
+        duration: animationDuration,
+        useNativeDriver: true,
+      }).start();
+
       _hideControls();
-    }, [_hideControls, isControlsVisible, onShowControls]);
+    }, [
+      onShowControls,
+      isControlsVisible,
+      animationValue,
+      animationDuration,
+      _hideControls,
+    ]);
 
     useEffect(() => {
       if (autoplay) _hideControls();
@@ -451,7 +488,13 @@ const VideoPlayerComponent = forwardRef(
 
     const renderControls = useCallback(
       () => (
-        <View style={[styles.controls, customStyles.controls]}>
+        <Animated.View
+          style={[
+            styles.controls,
+            customStyles.controls,
+            { transform: [{ translateY: controlsTranslateY }] },
+          ]}
+        >
           <TouchableOpacity
             onPress={_onPlayPress}
             style={[
@@ -505,14 +548,15 @@ const VideoPlayerComponent = forwardRef(
               />
             </TouchableOpacity>
           )}
-        </View>
+        </Animated.View>
       ),
       [
         customStyles.controls,
         customStyles.controlButton,
         customStyles.playControl,
-        customStyles.controlIcon,
         customStyles.durationText,
+        customStyles.controlIcon,
+        controlsTranslateY,
         _onPlayPress,
         isPlaying,
         renderSeekBar,
@@ -529,7 +573,7 @@ const VideoPlayerComponent = forwardRef(
 
     const renderVideo = useCallback(
       () => (
-        <View style={customStyles.videoWrapper}>
+        <View style={[{ overflow: 'hidden' }, customStyles.videoWrapper]}>
           <Video
             {...props}
             ref={videoRef}