diff --git a/src/components/VideoPlayer/SubtitleManager.tsx b/src/components/VideoPlayer/SubtitleManager.tsx
index 21fa586..e117032 100644
--- a/src/components/VideoPlayer/SubtitleManager.tsx
+++ b/src/components/VideoPlayer/SubtitleManager.tsx
@@ -58,13 +58,15 @@ import {
   showLoading,
   showSuccess,
 } from "../../utils/toast";
-interface SubtitleManagerProps {
+
+
+export interface SubtitleManagerProps {
   qortalMetadata: QortalGetMetadata;
   close: () => void;
   open: boolean;
   onSelect: (subtitle: SubtitlePublishedData) => void;
   subtitleBtnRef: any;
-  currentSubTrack: null | string;
+  currentSubTrack: null | string
 }
 export interface Subtitle {
   language: string | null;
@@ -123,7 +125,7 @@ const SubtitleManagerComponent = ({
       setIsLoading(true);
       const videoId = `${qortalMetadata?.service}-${qortalMetadata?.name}-${qortalMetadata?.identifier}`;
       console.log("videoId", videoId);
-      const postIdSearch = await identifierOperations.buildSearchPrefix(
+      const postIdSearch = await identifierOperations.buildLooseSearchPrefix(
         ENTITY_SUBTITLE,
         videoId
       );
@@ -179,16 +181,16 @@ const SubtitleManagerComponent = ({
     try {
       const videoId = `${qortalMetadata?.service}-${qortalMetadata?.name}-${qortalMetadata?.identifier}`;
 
-      const identifier = await identifierOperations.buildIdentifier(
-        ENTITY_SUBTITLE,
-        videoId
-      );
+     
       const name = auth?.name;
-      console.log("identifier2", identifier);
       if (!name) return;
       const resources: ResourceToPublish[] = [];
       const tempResources: { qortalMetadata: QortalMetadata; data: any }[] = [];
       for (const sub of subtitles) {
+         const identifier = await identifierOperations.buildLooseIdentifier(
+        ENTITY_SUBTITLE,
+        videoId
+      );
         const data = {
           subtitleData: sub.base64,
           language: sub.language,
diff --git a/src/components/VideoPlayer/TimelineActionsComponent.tsx b/src/components/VideoPlayer/TimelineActionsComponent.tsx
new file mode 100644
index 0000000..c32677a
--- /dev/null
+++ b/src/components/VideoPlayer/TimelineActionsComponent.tsx
@@ -0,0 +1,72 @@
+import React, { useCallback, useMemo, useState } from 'react'
+import { TimelineAction } from './VideoPlayer'
+import { alpha, Box, ButtonBase, Popover, Typography } from '@mui/material'
+
+interface TimelineActionsComponentProps {
+timelineActions: TimelineAction[]
+progress: number
+containerRef: any
+seekTo: (time: number)=> void
+
+}
+
+const placementStyles: Record<NonNullable<TimelineAction['placement']>, React.CSSProperties> = {
+  'TOP-RIGHT': { top: 16, right: 16 },
+  'TOP-LEFT': { top: 16, left: 16 },
+  'BOTTOM-LEFT': { bottom: 60, left: 16 },
+  'BOTTOM-RIGHT': { bottom: 60, right: 16 },
+};
+
+export const TimelineActionsComponent = ({timelineActions, progress, containerRef, seekTo}: TimelineActionsComponentProps) => {
+    const [isOpen, setIsOpen] = useState(true)
+
+    const handleClick = useCallback((action: TimelineAction)=> {
+        if(action?.type === 'SEEK'){
+            if(!action?.seekToTime) return
+            seekTo(action.seekToTime)
+        } else if(action?.type === 'CUSTOM'){
+            if(action.onClick){
+                action.onClick()
+            }
+        }
+    },[])
+
+      // Find the current matching action(s)
+  const activeActions = useMemo(() => {
+    return timelineActions.filter(action => {
+      return progress >= action.time && progress <= action.time + action.duration;
+    });
+  }, [timelineActions, progress]);
+
+  const hasActive = activeActions.length > 0;
+
+  if (!hasActive) return null; // Don’t render unless active
+  return (
+    <>
+    {activeActions.map((action, index) => {
+        const placement = (action.placement ?? 'TOP-RIGHT') as keyof typeof placementStyles;
+
+        return (
+            <ButtonBase
+      sx={{
+        position: 'absolute',
+        bgcolor: alpha("#181818", 0.95),
+        p: 1,
+        borderRadius: 1,
+        boxShadow: 3,
+        zIndex: 10,
+        outline: '1px solid white',
+          ...placementStyles[placement || 'TOP-RIGHT'],
+      }}
+    >
+      
+        <Typography key={index} variant="body2" onClick={()=> handleClick(action)}>
+          {action.label}
+        </Typography>
+      
+    </ButtonBase>
+        )
+    } )}
+    </>
+  )
+}
diff --git a/src/components/VideoPlayer/VideoPlayer-styles.ts b/src/components/VideoPlayer/VideoPlayer-styles.ts
index 903148d..69c74f2 100644
--- a/src/components/VideoPlayer/VideoPlayer-styles.ts
+++ b/src/components/VideoPlayer/VideoPlayer-styles.ts
@@ -17,11 +17,7 @@ export const VideoContainer = styled(Box)(({ theme }) => ({
 }));
 
 export const VideoElement = styled("video")(({ theme }) => ({
-  position: 'absolute',
-  top: 0,
-  bottom: 0,
-  right: 0,
-  left: 0,
+
   background: "rgb(33, 33, 33)",
 
   "&:focus": {
diff --git a/src/components/VideoPlayer/VideoPlayer.tsx b/src/components/VideoPlayer/VideoPlayer.tsx
index 73c18b1..6fffcc7 100644
--- a/src/components/VideoPlayer/VideoPlayer.tsx
+++ b/src/components/VideoPlayer/VideoPlayer.tsx
@@ -22,10 +22,12 @@ import Player from "video.js/dist/types/player";
 import {
   Subtitle,
   SubtitleManager,
+  SubtitleManagerProps,
   SubtitlePublishedData,
 } from "./SubtitleManager";
 import { base64ToBlobUrl } from "../../utils/base64";
 import convert from "srt-webvtt";
+import { TimelineActionsComponent } from "./TimelineActionsComponent";
 
 export async function srtBase64ToVttBlobUrl(
   base64Srt: string
@@ -51,6 +53,24 @@ export async function srtBase64ToVttBlobUrl(
 }
 type StretchVideoType = "contain" | "fill" | "cover" | "none" | "scale-down";
 
+export type TimelineAction =
+  | {
+      type: 'SEEK';
+      time: number;
+      duration: number;
+      label: string;
+      onClick?: () => void; 
+      seekToTime: number; // ✅ Required for SEEK
+      placement?: 'TOP-RIGHT' | 'TOP-LEFT' | 'BOTTOM-LEFT' | 'BOTTOM-RIGHT';
+    }
+  | {
+      type: 'CUSTOM';
+      time: number;
+      duration: number;
+      label: string;
+      onClick: () => void; // ✅ Required for CUSTOM
+      placement?: 'TOP-RIGHT' | 'TOP-LEFT' | 'BOTTOM-LEFT' | 'BOTTOM-RIGHT';
+    };
 interface VideoPlayerProps {
   qortalVideoResource: QortalGetMetadata;
   videoRef: Ref<HTMLVideoElement>;
@@ -58,8 +78,11 @@ interface VideoPlayerProps {
   poster?: string;
   autoPlay?: boolean;
   onEnded?: (e: React.SyntheticEvent<HTMLVideoElement, Event>) => void;
+  timelineActions?: TimelineAction[]
 }
 
+
+
 const videoStyles = {
   videoContainer: {},
   video: {},
@@ -160,6 +183,7 @@ export const VideoPlayer = ({
   poster,
   autoPlay,
   onEnded,
+  timelineActions
 }: VideoPlayerProps) => {
   const containerRef = useRef<RefObject<HTMLDivElement> | null>(null);
   const [videoObjectFit] = useState<StretchVideoType>("contain");
@@ -207,6 +231,7 @@ export const VideoPlayer = ({
     percentLoaded,
     showControlsFullScreen,
     onSelectPlaybackRate,
+    seekTo
   } = useVideoPlayerController({
     autoPlay,
     playerRef,
@@ -324,7 +349,7 @@ export const VideoPlayer = ({
   const videoStylesContainer = useMemo(() => {
     return {
       cursor: showControls ? "auto" : "none",
-      aspectRatio: "16 / 9",
+      // aspectRatio: "16 / 9",
       ...videoStyles?.videoContainer,
     };
   }, [showControls]);
@@ -584,9 +609,9 @@ export const VideoPlayer = ({
           autoplay: true,
           controls: false,
           responsive: true,
-          fluid: true,
+          // fluid: true,
           poster: startPlay ? "" : poster,
-          aspectRatio: "16:9",
+          // aspectRatio: "16:9",
           sources: [
             {
               src: resourceUrl,
@@ -758,7 +783,10 @@ export const VideoPlayer = ({
             toggleMute={toggleMute}
           />
         )}
+  {timelineActions && Array.isArray(timelineActions) && (
+            <TimelineActionsComponent seekTo={seekTo} containerRef={containerRef} progress={localProgress} timelineActions={timelineActions}/>
 
+  )}
         <SubtitleManager
           subtitleBtnRef={subtitleBtnRef}
           close={closeSubtitleManager}
diff --git a/src/components/VideoPlayer/useVideoPlayerController.tsx b/src/components/VideoPlayer/useVideoPlayerController.tsx
index 18f5894..343d160 100644
--- a/src/components/VideoPlayer/useVideoPlayerController.tsx
+++ b/src/components/VideoPlayer/useVideoPlayerController.tsx
@@ -217,6 +217,17 @@ try {
 }
 }, []);
 
+ const seekTo = useCallback((time: number) => {
+try {
+    const player = playerRef.current;
+  if (!player || typeof player.duration !== 'function' || typeof player.currentTime !== 'function') return;
+
+  player.currentTime(time);
+} catch (error) {
+  console.error('setProgressAbsolute', error)
+}
+}, []);
+
 
   const toggleObjectFit = useCallback(() => {
     setVideoObjectFit(videoObjectFit === "contain" ? "fill" : "contain");
@@ -303,6 +314,6 @@ const togglePlay = useCallback(async () => {
     isReady,
     resourceUrl,
     startPlay,
-    status, percentLoaded, showControlsFullScreen, onSelectPlaybackRate: updatePlaybackRate
+    status, percentLoaded, showControlsFullScreen, onSelectPlaybackRate: updatePlaybackRate, seekTo
   };
 };
diff --git a/src/hooks/useIdentifiers.tsx b/src/hooks/useIdentifiers.tsx
index f874023..d880918 100644
--- a/src/hooks/useIdentifiers.tsx
+++ b/src/hooks/useIdentifiers.tsx
@@ -1,6 +1,8 @@
 import React, { useCallback, useMemo } from "react";
 import {
   buildIdentifier,
+  buildLooseIdentifier,
+  buildLooseSearchPrefix,
   buildSearchPrefix,
   EnumCollisionStrength,
   hashWord,
@@ -60,6 +62,8 @@ export const useIdentifiers = (publicSalt: string, appName: string) => {
       createSingleIdentifier,
       hashQortalName,
       hashString,
+      buildLooseSearchPrefix,
+      buildLooseIdentifier
     }),
     [
       buildIdentifierFunc,
diff --git a/src/index.ts b/src/index.ts
index acd86de..7eff849 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,6 +4,7 @@ export { useResourceStatus } from './hooks/useResourceStatus';
 export { Spacer } from './common/Spacer';
 export { useModal } from './hooks/useModal';
 export { AudioPlayerControls , OnTrackChangeMeta, AudioPlayerProps, AudioPlayerHandle} from './components/AudioPlayer/AudioPlayerControls';
+export {TimelineAction} from './components/VideoPlayer/VideoPlayer'
 export { useAudioPlayerHotkeys } from './components/AudioPlayer/useAudioPlayerHotkeys';
 export { VideoPlayer } from './components/VideoPlayer/VideoPlayer';
 export { useListReturn } from './hooks/useListData';
diff --git a/src/utils/encryption.ts b/src/utils/encryption.ts
index 008ee04..3cc9b59 100644
--- a/src/utils/encryption.ts
+++ b/src/utils/encryption.ts
@@ -129,6 +129,33 @@ export async function buildSearchPrefix(
     : `${appHash}-${entityPrefix}-`; // ✅ Global search for entity type
 }
 
+export async function buildLooseSearchPrefix(
+  entityType: string,
+  parentId?: string | null
+): Promise<string> {
+  // Hash entity type (6 chars)
+  const entityPrefix: string = await hashWord(
+    entityType,
+    EnumCollisionStrength.ENTITY_LABEL,
+    ""
+  );
+
+  let parentRef = "";
+  if (parentId === null) {
+    parentRef = "00000000000000"; // for true root entities
+  } else if (parentId) {
+    parentRef = await hashWord(
+      parentId,
+      EnumCollisionStrength.PARENT_REF,
+      ""
+    );
+  }
+
+  return parentRef
+    ? `${entityPrefix}-${parentRef}-` // for nested entity searches
+    : `${entityPrefix}-`; // global entity type prefix
+}
+
 // Function to generate IDs dynamically with `publicSalt`
 export async function buildIdentifier(
   appName: string,
@@ -166,6 +193,33 @@ export async function buildIdentifier(
   return `${appHash}-${entityPrefix}-${parentRef}-${entityUid}-${IDENTIFIER_BUILDER_VERSION}`;
 }
 
+export async function buildLooseIdentifier(
+  entityType: string,
+  parentId?: string | null
+): Promise<string> {
+  // 4-char hash for entity type
+  const entityPrefix: string = await hashWord(
+    entityType,
+    EnumCollisionStrength.ENTITY_LABEL,
+    ""
+  );
+
+  // Generate 8-12 character random uid (depends on uid.rnd() settings)
+  const entityUid = uid.rnd();
+
+  // Optional hashed parent ref
+  let parentRef = '';
+  if (parentId) {
+    parentRef = await hashWord(
+      parentId,
+      EnumCollisionStrength.PARENT_REF,
+      ""
+    );
+  }
+
+  return `${entityPrefix}${parentRef ? `-${parentRef}` : ''}-${entityUid}${IDENTIFIER_BUILDER_VERSION ? `-${IDENTIFIER_BUILDER_VERSION}` : ''}`;
+}
+
 export const createSymmetricKeyAndNonce = () => {
   const messageKey = new Uint8Array(32); // 32 bytes for the symmetric key
   crypto.getRandomValues(messageKey);