diff --git a/cms/version.py b/cms/version.py index 8f5a37ae..0c8dd709 100644 --- a/cms/version.py +++ b/cms/version.py @@ -1 +1 @@ -VERSION = "7.0.0" +VERSION = "7.0.1-beta.8" diff --git a/frontend-tools/chapters-editor/client/src/App.tsx b/frontend-tools/chapters-editor/client/src/App.tsx index 1fefad96..4e0b8f1c 100644 --- a/frontend-tools/chapters-editor/client/src/App.tsx +++ b/frontend-tools/chapters-editor/client/src/App.tsx @@ -96,7 +96,8 @@ const App = () => { case 'ArrowLeft': event.preventDefault(); if (videoRef.current) { - const newTime = Math.max(currentTime - 10, 0); + // Use the video element's current time directly to avoid stale state + const newTime = Math.max(videoRef.current.currentTime - 10, 0); handleMobileSafeSeek(newTime); logger.debug('Jumped backward 10 seconds to:', formatDetailedTime(newTime)); } @@ -104,7 +105,8 @@ const App = () => { case 'ArrowRight': event.preventDefault(); if (videoRef.current) { - const newTime = Math.min(currentTime + 10, duration); + // Use the video element's current time directly to avoid stale state + const newTime = Math.min(videoRef.current.currentTime + 10, duration); handleMobileSafeSeek(newTime); logger.debug('Jumped forward 10 seconds to:', formatDetailedTime(newTime)); } @@ -117,7 +119,7 @@ const App = () => { return () => { document.removeEventListener('keydown', handleKeyDown); }; - }, [handlePlay, handleMobileSafeSeek, currentTime, duration, videoRef]); + }, [handlePlay, handleMobileSafeSeek, duration, videoRef]); return (
diff --git a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx index f7e79066..1f609713 100644 --- a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx +++ b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx @@ -589,12 +589,13 @@ const TimelineControls = ({ // Update display time and check for transitions between segments and empty spaces useEffect(() => { - // Always update display time to match current video time when playing + // Always update display time to match current video time if (videoRef.current) { - // If video is playing, always update the displayed time in the tooltip + // Always update display time when current time changes (both playing and paused) + setDisplayTime(currentTime); + + // If video is playing, also update the tooltip and perform segment checks if (!videoRef.current.paused) { - setDisplayTime(currentTime); - // Also update clicked time to keep them in sync when playing // This ensures correct time is shown when pausing setClickedTime(currentTime); diff --git a/frontend-tools/video-editor/client/src/App.tsx b/frontend-tools/video-editor/client/src/App.tsx index a8a48bb6..5428a068 100644 --- a/frontend-tools/video-editor/client/src/App.tsx +++ b/frontend-tools/video-editor/client/src/App.tsx @@ -253,7 +253,8 @@ const App = () => { case 'ArrowLeft': event.preventDefault(); if (videoRef.current) { - const newTime = Math.max(currentTime - 10, 0); + // Use the video element's current time directly to avoid stale state + const newTime = Math.max(videoRef.current.currentTime - 10, 0); handleMobileSafeSeek(newTime); logger.debug('Jumped backward 10 seconds to:', formatDetailedTime(newTime)); } @@ -261,7 +262,8 @@ const App = () => { case 'ArrowRight': event.preventDefault(); if (videoRef.current) { - const newTime = Math.min(currentTime + 10, duration); + // Use the video element's current time directly to avoid stale state + const newTime = Math.min(videoRef.current.currentTime + 10, duration); handleMobileSafeSeek(newTime); logger.debug('Jumped forward 10 seconds to:', formatDetailedTime(newTime)); } @@ -274,7 +276,7 @@ const App = () => { return () => { document.removeEventListener('keydown', handleKeyDown); }; - }, [handlePlay, handleMobileSafeSeek, currentTime, duration, videoRef]); + }, [handlePlay, handleMobileSafeSeek, duration, videoRef]); return (
diff --git a/frontend-tools/video-editor/client/src/components/TimelineControls.tsx b/frontend-tools/video-editor/client/src/components/TimelineControls.tsx index a43fc8d0..f24a9920 100644 --- a/frontend-tools/video-editor/client/src/components/TimelineControls.tsx +++ b/frontend-tools/video-editor/client/src/components/TimelineControls.tsx @@ -779,12 +779,13 @@ const TimelineControls = ({ // Update display time and check for transitions between segments and empty spaces useEffect(() => { - // Always update display time to match current video time when playing + // Always update display time to match current video time if (videoRef.current) { - // If video is playing, always update the displayed time in the tooltip + // Always update display time when current time changes (both playing and paused) + setDisplayTime(currentTime); + + // If video is playing, also update the tooltip and perform segment checks if (!videoRef.current.paused) { - setDisplayTime(currentTime); - // Also update clicked time to keep them in sync when playing // This ensures correct time is shown when pausing setClickedTime(currentTime); diff --git a/frontend-tools/video-js/index-embed-old.html b/frontend-tools/video-js/index-embed-old.html deleted file mode 100644 index 71716245..00000000 --- a/frontend-tools/video-js/index-embed-old.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - VideoJS - - -
-
-
- - - diff --git a/frontend-tools/video-js/index-old.html b/frontend-tools/video-js/index-old.html deleted file mode 100644 index d5c6db6d..00000000 --- a/frontend-tools/video-js/index-old.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - VideoJS - - -
- - - diff --git a/frontend-tools/video-js/src/assets/sample-media-file.json b/frontend-tools/video-js/src/assets/sample-media-file.json index a261c857..02ae30a1 100644 --- a/frontend-tools/video-js/src/assets/sample-media-file.json +++ b/frontend-tools/video-js/src/assets/sample-media-file.json @@ -1,79 +1,70 @@ { - "url": "https://videojs.mediacms.io/view?m=d8vz3n3PZ", - "user": "markos", - "title": "ExitofElygiaGorge,Chania,Crete.mp4 (Trimmed)", - "description": "Checkout an awesome timestamp at 00:00:14 and another one is 00:00:24", - "add_date": "2025-09-25T13:12:26.160968+01:00", - "edit_date": "2025-09-25T13:12:26.403883+01:00", + "url": "https://deic.mediacms.io/view?m=mNm3XcqOm", + "user": "giannis", + "title": "samplevideo10m.mp4", + "description": "", + "add_date": "2025-06-24T12:43:03.640948+01:00", + "edit_date": "2025-10-25T12:50:37.898321+01:00", "media_type": "video", - "state": "public", - "duration": 20, - "thumbnail_url": "/media/original/thumbnails/user/markos/d393b72d279d4d0da70a484eb6b8b44f_XEowv3s.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.jpg", - "poster_url": "/media/original/thumbnails/user/markos/d393b72d279d4d0da70a484eb6b8b44f_1JFT5EJ.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.jpg", + "state": "private", + "duration": 608, + "thumbnail_url": "/media/original/thumbnails/user/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd_shMkDEC.samplevideo10m.mp4.jpg", + "poster_url": "/media/original/thumbnails/user/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd_YkFI3Fg.samplevideo10m.mp4.jpg", "thumbnail_time": null, - "sprites_url": "/media/original/thumbnails/user/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4sprites.jpg", - "preview_url": "/media/encoded/1/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.tmpm_mh1zlk.gif", - "author_name": "Markos", - "author_profile": "/user/markos/", - "author_thumbnail": "/media/userlogos/2025/09/23/markos.jpeg", + "sprites_url": "/media/original/thumbnails/user/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4sprites.jpg", + "preview_url": "/media/encoded/1/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.tmpvldjbxzb.gif", + "author_name": "Giannis Christodoulou", + "author_profile": "/user/giannis/", + "author_thumbnail": "/media/userlogos/user.jpg", "encodings_info": { - "144": { - "h264": { - "title": "h264-144", - "url": "/media/encoded/23/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", - "progress": 100, - "size": "0.9MB", - "encoding_id": 157, - "status": "success" - } - }, + "144": {}, "240": { "h264": { "title": "h264-240", - "url": "/media/encoded/2/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", + "url": "/media/encoded/2/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4.mp4", "progress": 100, - "size": "1.5MB", - "encoding_id": 160, + "size": "3.4MB", + "encoding_id": 2367, "status": "success" } }, "360": { "h264": { "title": "h264-360", - "url": "/media/encoded/3/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", + "url": "/media/encoded/3/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4.mp4", "progress": 100, - "size": "2.3MB", - "encoding_id": 158, + "size": "4.7MB", + "encoding_id": 2368, "status": "success" } }, "480": { "h264": { "title": "h264-480", - "url": "/media/encoded/13/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", + "url": "/media/encoded/13/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4.mp4", "progress": 100, - "size": "4.2MB", - "encoding_id": 154, + "size": "6.2MB", + "encoding_id": 2369, "status": "success" } }, "720": { "h264": { "title": "h264-720", - "url": "/media/encoded/10/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", + "url": "/media/encoded/10/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4.mp4", "progress": 100, - "size": "12.2MB", - "encoding_id": 155, + "size": "8.9MB", + "encoding_id": 2370, "status": "success" } }, "1080": { "h264": { "title": "h264-1080", - "url": "/media/encoded/7/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4.mp4", + "url": "/media/encoded/7/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4.mp4", "progress": 100, - "size": "25.9MB", - "encoding_id": 159, + "size": "13.8MB", + "encoding_id": 2371, "status": "success" } }, @@ -81,1160 +72,54 @@ "2160": {} }, "encoding_status": "success", - "views": 58, + "views": 5, "likes": 1, "dislikes": 0, "reported_times": 0, "user_featured": false, - "original_media_url": "/media/original/user/markos/d393b72d279d4d0da70a484eb6b8b44f.c4668407eb354740a35d933ed7d2786c.ExitofElygiaGorgeChaniaCrete.mp4", - "size": "49.1MB", + "original_media_url": "/media/original/user/giannis/5bdc2acc8a254c4da09b5af92fcc7ebd.samplevideo10m.mp4", + "size": "43.5MB", "video_height": 1080, "enable_comments": true, "categories_info": [], "is_reviewed": true, - "edit_url": "/edit?m=d8vz3n3PZ", + "edit_url": "/edit?m=mNm3XcqOm", "tags_info": [], "hls_info": { - "master_file": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/master.m3u8", - "720_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-1/iframes.m3u8", - "144_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-2/iframes.m3u8", - "360_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-3/iframes.m3u8", - "1080_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-4/iframes.m3u8", - "240_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-5/iframes.m3u8", - "480_iframe": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-6/iframes.m3u8", - "720_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-1/stream.m3u8", - "144_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-2/stream.m3u8", - "360_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-3/stream.m3u8", - "1080_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-4/stream.m3u8", - "240_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-5/stream.m3u8", - "480_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-6/stream.m3u8" + "master_file": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/master.m3u8", + "1080_iframe": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-1/iframes.m3u8", + "720_iframe": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-2/iframes.m3u8", + "480_iframe": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-3/iframes.m3u8", + "360_iframe": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-4/iframes.m3u8", + "240_iframe": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-5/iframes.m3u8", + "1080_playlist": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-1/stream.m3u8", + "720_playlist": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-2/stream.m3u8", + "480_playlist": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-3/stream.m3u8", + "360_playlist": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-4/stream.m3u8", + "240_playlist": "/media/hls/5bdc2acc8a254c4da09b5af92fcc7ebd/media-5/stream.m3u8" }, "license": null, - "__subtitles_info": [ - { - "src": "https://videojs.mediacms.io/media/original/subtitles/user/markos/7e5aaed284954ae497d09783bf81004f.ExitofElygiaGorgeChaniaCrete.vtt", - "srclang": "en", - "label": "English" - } - ], + "subtitles_info": [], "chapter_data": [ { - "startTime": "00:00:00.000", - "endTime": "00:00:02.322", - "chapterTitle": "Chapter 1" + "startTime": "00:00:37.184", + "endTime": "00:01:45.969", + "chapterTitle": "test1" }, { - "startTime": "00:00:03.786", - "endTime": "00:00:06.049", - "chapterTitle": "Chapter 2" + "startTime": "00:02:23.423", + "endTime": "00:05:18.439", + "chapterTitle": "test2" }, { - "startTime": "00:00:07.864", - "endTime": "00:00:10.791", - "chapterTitle": "Chapter 3" - }, - { - "startTime": "00:00:12.411", - "endTime": "00:00:19.514", - "chapterTitle": "Chapter 4" + "startTime": "00:05:57.580", + "endTime": "00:08:12.337", + "chapterTitle": "test3" } ], "ratings_info": [], - "add_subtitle_url": "/add_subtitle?m=d8vz3n3PZ", + "add_subtitle_url": "/add_subtitle?m=mNm3XcqOm", "allow_download": true, "slideshow_items": [], - "related_media": [ - { - "friendly_token": "YprzLzICe", - "url": "https://videojs.mediacms.io/view?m=YprzLzICe", - "api_url": "https://videojs.mediacms.io/api/v1/media/YprzLzICe", - "user": "admin", - "title": "14249923_3840_2160_60fps.mp4", - "description": "", - "add_date": "2025-09-23T13:05:09.930906+01:00", - "views": 47, - "media_type": "video", - "state": "public", - "duration": 15, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/682cdbf87bb14826b5cf2146384e7498_mpSPxdc.14249923_3840_2160_60fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/682cdbf87bb14826b5cf2146384e7498.tmpyusu9afm.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "71.9MB" - }, - { - "friendly_token": "2Uk08Il5u", - "url": "https://videojs.mediacms.io/view?m=2Uk08Il5u", - "api_url": "https://videojs.mediacms.io/api/v1/media/2Uk08Il5u", - "user": "markos", - "title": "A video without HLS", - "description": "", - "add_date": "2025-09-16T12:40:55+01:00", - "views": 68, - "media_type": "video", - "state": "public", - "duration": 27, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/db52140de7204022a1e5f08e078b4ec6_02xAHoZ.UniversityofCopenhagenM%C3%A6rskTower.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/db52140de7204022a1e5f08e078b4ec6.tmpuespp_ik.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "58.8MB" - }, - { - "friendly_token": "v7MDJVk6z", - "url": "https://videojs.mediacms.io/view?m=v7MDJVk6z", - "api_url": "https://videojs.mediacms.io/api/v1/media/v7MDJVk6z", - "user": "admin", - "title": "20233414hd_2048_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:08.710882+01:00", - "views": 9, - "media_type": "video", - "state": "public", - "duration": 37, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/c4e70c90cc004d6aab2204a057787b17_htzxbCC.20233414hd_2048_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/c4e70c90cc004d6aab2204a057787b17.tmpn4pfbu27.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "26.9MB" - }, - { - "friendly_token": "GrtvaYVVc", - "url": "https://videojs.mediacms.io/view?m=GrtvaYVVc", - "api_url": "https://videojs.mediacms.io/api/v1/media/GrtvaYVVc", - "user": "testme", - "title": "20250725_194342.mp4", - "description": "", - "add_date": "2025-07-25T19:54:09.496404+01:00", - "views": 66, - "media_type": "video", - "state": "public", - "duration": 60, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/testme/6bb22eae99f74ee59e0af5d3aa54ded6_7i3CQ53.20250725_194342.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/testme/6bb22eae99f74ee59e0af5d3aa54ded6.tmpu2_qmcuu.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/testme/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "130.9MB" - }, - { - "friendly_token": "cX4A2xLym", - "url": "https://videojs.mediacms.io/view?m=cX4A2xLym", - "api_url": "https://videojs.mediacms.io/api/v1/media/cX4A2xLym", - "user": "markos", - "title": "VID_20230122_134550.mp4", - "description": "", - "add_date": "2025-09-15T14:52:53.159939+01:00", - "views": 30, - "media_type": "video", - "state": "public", - "duration": 7, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/c2a120930e934a1aa3f7230426800b30_9I7Hvhl.VID_20230122_134550.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/c2a120930e934a1aa3f7230426800b30.tmp4qgw2m2t.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "18.0MB" - }, - { - "friendly_token": "ieLetJSzc", - "url": "https://videojs.mediacms.io/view?m=ieLetJSzc", - "api_url": "https://videojs.mediacms.io/api/v1/media/ieLetJSzc", - "user": "casto", - "title": "test_audio.mp3", - "description": "", - "add_date": "2025-10-13T10:45:10.633098+01:00", - "views": 8, - "media_type": "audio", - "state": "public", - "duration": 1536, - "thumbnail_url": null, - "is_reviewed": true, - "preview_url": null, - "author_name": "Casper Tollund", - "author_profile": "https://videojs.mediacms.io/user/casto/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "HXqM3h77T", - "url": "https://videojs.mediacms.io/view?m=HXqM3h77T", - "api_url": "https://videojs.mediacms.io/api/v1/media/HXqM3h77T", - "user": "markos", - "title": "VID_20231226_003812.mp4", - "description": "", - "add_date": "2025-09-15T14:50:20+01:00", - "views": 72, - "media_type": "video", - "state": "public", - "duration": 52, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/DSC07691_Weawux4.JPG", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/da71ed534ff7431aa96dd3cd4e03b61a.tmpz3nbwhcu.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "132.1MB" - }, - { - "friendly_token": "ClYscEzph", - "url": "https://videojs.mediacms.io/view?m=ClYscEzph", - "api_url": "https://videojs.mediacms.io/api/v1/media/ClYscEzph", - "user": "yiannis@web357.com", - "title": "samplevideo.mp3", - "description": "", - "add_date": "2025-09-23T13:31:43+01:00", - "views": 27, - "media_type": "audio", - "state": "public", - "duration": 221, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/yiannis@web357.com/0_84mclyg0_copy_2_TxO7VxC.jpg", - "is_reviewed": true, - "preview_url": null, - "author_name": "Yiannis", - "author_profile": "https://videojs.mediacms.io/user/yiannis@web357.com/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "op9FK7V5W", - "url": "https://videojs.mediacms.io/view?m=op9FK7V5W", - "api_url": "https://videojs.mediacms.io/api/v1/media/op9FK7V5W", - "user": "markos", - "title": "KastaniaEvrytanias,CentralGreece.mp4", - "description": "", - "add_date": "2025-09-16T12:40:17+01:00", - "views": 40, - "media_type": "video", - "state": "public", - "duration": 25, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/99866d1f90354360a6de6d1b269cee8a_ceEIIZx.KastaniaEvrytaniasCentralGreece.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/99866d1f90354360a6de6d1b269cee8a.tmpjalqxuhn.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "54.3MB" - }, - { - "friendly_token": "qWZDxnF6j", - "url": "https://videojs.mediacms.io/view?m=qWZDxnF6j", - "api_url": "https://videojs.mediacms.io/api/v1/media/qWZDxnF6j", - "user": "thorkildjensen", - "title": "13502237_4096_2160_24fps.mp4", - "description": "", - "add_date": "2025-09-22T08:24:34+01:00", - "views": 38, - "media_type": "video", - "state": "public", - "duration": 18, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/thorkildjensen/0a68c8f4fb93454a8c1feceb91c55619_hImy7D7.13502237_4096_2160_24fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/thorkildjensen/0a68c8f4fb93454a8c1feceb91c55619.tmpp70pluvg.gif", - "author_name": "Thorkild Jensen", - "author_profile": "https://videojs.mediacms.io/user/thorkildjensen/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "37.6MB" - }, - { - "friendly_token": "tHZZaCAbG", - "url": "https://videojs.mediacms.io/view?m=tHZZaCAbG", - "api_url": "https://videojs.mediacms.io/api/v1/media/tHZZaCAbG", - "user": "admin", - "title": "Tracking_Hvemfolgerdigpaanettet?Source.mp3", - "description": "", - "add_date": "2025-09-25T09:49:16+01:00", - "views": 29, - "media_type": "audio", - "state": "public", - "duration": 1536, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/0_84mclyg0_Ox2vkM6_aH0oho2.jpg", - "is_reviewed": true, - "preview_url": null, - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "lblIBR20P", - "url": "https://videojs.mediacms.io/view?m=lblIBR20P", - "api_url": "https://videojs.mediacms.io/api/v1/media/lblIBR20P", - "user": "markos", - "title": "video.mp4 1", - "description": "", - "add_date": "2025-07-08T00:00:00+01:00", - "views": 140, - "media_type": "video", - "state": "public", - "duration": 7, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/9cccc9090798474b98b63937753dde8c_MtuuUc2.video.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/9cccc9090798474b98b63937753dde8c.tmpc9qbk5oj.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "19.2MB" - }, - { - "friendly_token": "qzuncxJyg", - "url": "https://videojs.mediacms.io/view?m=qzuncxJyg", - "api_url": "https://videojs.mediacms.io/api/v1/media/qzuncxJyg", - "user": "admin", - "title": "19247660hd_1920_1080_60fps.mp4", - "description": "", - "add_date": "2025-09-30T15:16:28+01:00", - "views": 21, - "media_type": "video", - "state": "public", - "duration": 8, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/43cc73a8c1604425b7057ad2b50b1798.19247660hd_1920_1080_60fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/43cc73a8c1604425b7057ad2b50b1798.tmpjuivwj8x.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "5.8MB" - }, - { - "friendly_token": "gqdbr5GQF", - "url": "https://videojs.mediacms.io/view?m=gqdbr5GQF", - "api_url": "https://videojs.mediacms.io/api/v1/media/gqdbr5GQF", - "user": "markos", - "title": "ritsoskarlob.jpg", - "description": "", - "add_date": "2025-07-08T13:36:29.632853+01:00", - "views": 23, - "media_type": "image", - "state": "public", - "duration": 0, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/6a8bf33be4b84451bc27ed5a30abd17f.ritsoskarlob.jpg.jpg", - "is_reviewed": true, - "preview_url": null, - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "GJZlb14qT", - "url": "https://videojs.mediacms.io/view?m=GJZlb14qT", - "api_url": "https://videojs.mediacms.io/api/v1/media/GJZlb14qT", - "user": "admin", - "title": "20315562hd_1920_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:10.444953+01:00", - "views": 10, - "media_type": "video", - "state": "public", - "duration": 8, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/44283493026346708eafde49c6ae5743_Cl0JaTI.20315562hd_1920_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/44283493026346708eafde49c6ae5743.tmpmm5xmrfa.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "6.1MB" - }, - { - "friendly_token": "keVJnk9Qc", - "url": "https://videojs.mediacms.io/view?m=keVJnk9Qc", - "api_url": "https://videojs.mediacms.io/api/v1/media/keVJnk9Qc", - "user": "admin", - "title": "18084154hd_1920_1080_50fps.mp4", - "description": "", - "add_date": "2025-10-01T15:22:52.768899+01:00", - "views": 20, - "media_type": "video", - "state": "public", - "duration": 11, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/8a1ba14f0a1641768430d0ceb4ae44b6_N06NhEk.18084154hd_1920_1080_50fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/8a1ba14f0a1641768430d0ceb4ae44b6.tmpdvzd3vo9.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "5.2MB" - }, - { - "friendly_token": "OXA5YLgbR", - "url": "https://videojs.mediacms.io/view?m=OXA5YLgbR", - "api_url": "https://videojs.mediacms.io/api/v1/media/OXA5YLgbR", - "user": "admin", - "title": "20325563hd_1920_1080_60fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:12.701363+01:00", - "views": 26, - "media_type": "video", - "state": "public", - "duration": 5, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/00b2e0c02233417588e362db03840fad_ULyZDYI.20325563hd_1920_1080_60fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/00b2e0c02233417588e362db03840fad.tmpu2rz97fb.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "3.3MB" - }, - { - "friendly_token": "3o3F3l9Vb", - "url": "https://videojs.mediacms.io/view?m=3o3F3l9Vb", - "api_url": "https://videojs.mediacms.io/api/v1/media/3o3F3l9Vb", - "user": "markos", - "title": "ExitofElygiaGorge,Chania,Crete.mp4", - "description": "Checkout an awesome timestamp at 00:00:14 and another one is 00:00:24", - "add_date": "2025-09-16T12:41:36+01:00", - "views": 78, - "media_type": "video", - "state": "public", - "duration": 29, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/c4668407eb354740a35d933ed7d2786c_iDC7Dvv.ExitofElygiaGorgeChaniaCrete.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/c4668407eb354740a35d933ed7d2786c.tmpm_mh1zlk.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "75.6MB" - }, - { - "friendly_token": "cxridUpmN", - "url": "https://videojs.mediacms.io/view?m=cxridUpmN", - "api_url": "https://videojs.mediacms.io/api/v1/media/cxridUpmN", - "user": "yiannis@web357.com", - "title": "samplevideowhite.mp4", - "description": "", - "add_date": "2025-09-23T13:22:52.267985+01:00", - "views": 18, - "media_type": "video", - "state": "public", - "duration": 28, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/yiannis@web357.com/5073e97457004961a163c5b504e2d7e8_TPZjERG.samplevideowhite.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/yiannis@web357.com/5073e97457004961a163c5b504e2d7e8.tmpz7aaqgd2.gif", - "author_name": "Yiannis", - "author_profile": "https://videojs.mediacms.io/user/yiannis@web357.com/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "0.2MB" - }, - { - "friendly_token": "rcXVukhjR", - "url": "https://videojs.mediacms.io/view?m=rcXVukhjR", - "api_url": "https://videojs.mediacms.io/api/v1/media/rcXVukhjR", - "user": "markos", - "title": "VID_20230916_203950.mp4", - "description": "", - "add_date": "2025-09-15T14:51:34.686737+01:00", - "views": 54, - "media_type": "video", - "state": "public", - "duration": 17, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/8dda62d489734949a8e45ee7e57dcae3_lNlZGLY.VID_20230916_203950.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/8dda62d489734949a8e45ee7e57dcae3.tmpy0gdlfes.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "44.6MB" - }, - { - "friendly_token": "ywaw3XHp2", - "url": "https://videojs.mediacms.io/view?m=ywaw3XHp2", - "api_url": "https://videojs.mediacms.io/api/v1/media/ywaw3XHp2", - "user": "admin", - "title": "19093555hd_2048_1080_24fps.mp4", - "description": "", - "add_date": "2025-10-01T15:22:55.398583+01:00", - "views": 15, - "media_type": "video", - "state": "public", - "duration": 24, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/0be4bbdb807b4c05a1181534bf957114_xqBc2SX.19093555hd_2048_1080_24fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/0be4bbdb807b4c05a1181534bf957114.tmpgv0vmvk_.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "16.8MB" - }, - { - "friendly_token": "uNhnQvy44", - "url": "https://videojs.mediacms.io/view?m=uNhnQvy44", - "api_url": "https://videojs.mediacms.io/api/v1/media/uNhnQvy44", - "user": "admin", - "title": "deic16_06_MartinBechSource.mp4", - "description": "", - "add_date": "2025-10-03T10:50:31.589590+01:00", - "views": 69, - "media_type": "video", - "state": "public", - "duration": 31, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/9c0ebef31e044da18273958b4d7b4f58_Z8Gweou.deic16_06_MartinBechSource.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/9c0ebef31e044da18273958b4d7b4f58.tmpjorgd1it.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "10.5MB" - }, - { - "friendly_token": "adcPiBg8N", - "url": "https://videojs.mediacms.io/view?m=adcPiBg8N", - "api_url": "https://videojs.mediacms.io/api/v1/media/adcPiBg8N", - "user": "thorkildjensen", - "title": "13161886_3840_2160_30fps.mp4", - "description": "", - "add_date": "2025-09-22T08:24:23.619459+01:00", - "views": 35, - "media_type": "video", - "state": "public", - "duration": 17, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/thorkildjensen/876966ca37dd4b48870722f9a1a95365_ZiiI8cx.13161886_3840_2160_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/thorkildjensen/876966ca37dd4b48870722f9a1a95365.tmpgu8k9qm5.gif", - "author_name": "Thorkild Jensen", - "author_profile": "https://videojs.mediacms.io/user/thorkildjensen/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "82.6MB" - }, - { - "friendly_token": "FupnUqfc4", - "url": "https://videojs.mediacms.io/view?m=FupnUqfc4", - "api_url": "https://videojs.mediacms.io/api/v1/media/FupnUqfc4", - "user": "admin", - "title": "19128074hd_1920_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:22:57.622428+01:00", - "views": 29, - "media_type": "video", - "state": "public", - "duration": 37, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/504c2bc1d231406195dad39ac24fb2b6_QEDTRkr.19128074hd_1920_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/504c2bc1d231406195dad39ac24fb2b6.tmp7nrk9byi.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 2, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "24.9MB" - }, - { - "friendly_token": "PDDYW3FKT", - "url": "https://videojs.mediacms.io/view?m=PDDYW3FKT", - "api_url": "https://videojs.mediacms.io/api/v1/media/PDDYW3FKT", - "user": "admin", - "title": "19247660hd_1920_1080_60fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:02.024559+01:00", - "views": 14, - "media_type": "video", - "state": "public", - "duration": 8, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/f39569e5e5fc45218dbd04a5e484f8c1_IBZ6zrz.19247660hd_1920_1080_60fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/f39569e5e5fc45218dbd04a5e484f8c1.tmpp7fky5cw.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "5.8MB" - }, - { - "friendly_token": "8iNDqeAfg", - "url": "https://videojs.mediacms.io/view?m=8iNDqeAfg", - "api_url": "https://videojs.mediacms.io/api/v1/media/8iNDqeAfg", - "user": "yiannis@web357.com", - "title": "Magnamvelitipsumquisquamametmagnametincidunt.mp4", - "description": "", - "add_date": "2025-09-29T17:31:44.981327+01:00", - "views": 18, - "media_type": "video", - "state": "public", - "duration": 6, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/yiannis@web357.com/ca2def779e93418a9b9da919870bd526_WJegiqZ.Magnamvelitipsumquisquamametmagnametincidunt.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/yiannis@web357.com/ca2def779e93418a9b9da919870bd526.tmpr_cnt2t4.gif", - "author_name": "Yiannis", - "author_profile": "https://videojs.mediacms.io/user/yiannis@web357.com/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "13.0MB" - }, - { - "friendly_token": "Q7IufzPhn", - "url": "https://videojs.mediacms.io/view?m=Q7IufzPhn", - "api_url": "https://videojs.mediacms.io/api/v1/media/Q7IufzPhn", - "user": "admin", - "title": "5607902hd_1920_1080_24fps.mp4", - "description": "", - "add_date": "2025-09-30T15:16:16.757233+01:00", - "views": 12, - "media_type": "video", - "state": "public", - "duration": 10, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/16d54aefb6e441f0875a069ef3b1f4b7_HwEDnf5.5607902hd_1920_1080_24fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/16d54aefb6e441f0875a069ef3b1f4b7.tmp3ohrrdrr.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "6.0MB" - }, - { - "friendly_token": "9BuFyzHAB", - "url": "https://videojs.mediacms.io/view?m=9BuFyzHAB", - "api_url": "https://videojs.mediacms.io/api/v1/media/9BuFyzHAB", - "user": "casto", - "title": "blinking_controls.mov", - "description": "", - "add_date": "2025-10-02T15:05:29+01:00", - "views": 32, - "media_type": "video", - "state": "public", - "duration": 6, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/casto/b5f994242d61426daaa637ded4e0215f_Lngth06.blinking_controls.mov.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/casto/b5f994242d61426daaa637ded4e0215f.tmp920kwv6w.gif", - "author_name": "Casper Tollund", - "author_profile": "https://videojs.mediacms.io/user/casto/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 2, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "44.0MB" - }, - { - "friendly_token": "MPpjNAJ37", - "url": "https://videojs.mediacms.io/view?m=MPpjNAJ37", - "api_url": "https://videojs.mediacms.io/api/v1/media/MPpjNAJ37", - "user": "admin", - "title": "20576968hd_1920_1080_25fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:15.649931+01:00", - "views": 23, - "media_type": "video", - "state": "public", - "duration": 27, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/f0d604b8319648b3a5b2fca0ac04760b_MwJq72A.20576968hd_1920_1080_25fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/f0d604b8319648b3a5b2fca0ac04760b.tmp2fmp2ou_.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "19.5MB" - }, - { - "friendly_token": "bfdekixxV", - "url": "https://videojs.mediacms.io/view?m=bfdekixxV", - "api_url": "https://videojs.mediacms.io/api/v1/media/bfdekixxV", - "user": "admin", - "title": "TeknologienhjaelperhumanistiskforskningSource.mp3", - "description": "", - "add_date": "2025-09-25T09:49:15+01:00", - "views": 23, - "media_type": "audio", - "state": "public", - "duration": 2149, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/0_84mclyg0_uxHXW0A_QlEoygu.jpg", - "is_reviewed": true, - "preview_url": null, - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "aT8RBaCBT", - "url": "https://videojs.mediacms.io/view?m=aT8RBaCBT", - "api_url": "https://videojs.mediacms.io/api/v1/media/aT8RBaCBT", - "user": "markos", - "title": "Estipsumnonetinciduntvoluptatemadipiscilabore.mp4", - "description": "go to the best place: go to 00:04", - "add_date": "2025-09-16T12:39:41+01:00", - "views": 56, - "media_type": "video", - "state": "public", - "duration": 26, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/4fd9b683a76443cf9d754be55adc0091_U0XpnNl.Estipsumnonetinciduntvoluptatemadipiscilabore.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/4fd9b683a76443cf9d754be55adc0091.tmpyvc1vnrp.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "66.4MB" - }, - { - "friendly_token": "7VIy7inGZ", - "url": "https://videojs.mediacms.io/view?m=7VIy7inGZ", - "api_url": "https://videojs.mediacms.io/api/v1/media/7VIy7inGZ", - "user": "admin", - "title": "Hvemharbrugtnationalesupercomputere?Source.mp3", - "description": "", - "add_date": "2025-09-23T08:40:06+01:00", - "views": 34, - "media_type": "audio", - "state": "public", - "duration": 1839, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/0_84mclyg0_yVNkDBq.jpg", - "is_reviewed": true, - "preview_url": null, - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": null - }, - { - "friendly_token": "beae7lLVs", - "url": "https://videojs.mediacms.io/view?m=beae7lLVs", - "api_url": "https://videojs.mediacms.io/api/v1/media/beae7lLVs", - "user": "admin", - "title": "19990812hd_1920_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:06.413778+01:00", - "views": 19, - "media_type": "video", - "state": "public", - "duration": 36, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/c082bf4d565b47cf849909f92303c4f1_CIG2eav.19990812hd_1920_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/c082bf4d565b47cf849909f92303c4f1.tmp9nt688cs.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "25.2MB" - }, - { - "friendly_token": "VX2qAwiFd", - "url": "https://videojs.mediacms.io/view?m=VX2qAwiFd", - "api_url": "https://videojs.mediacms.io/api/v1/media/VX2qAwiFd", - "user": "markos", - "title": "VID_20230917_094453.mp4", - "description": "", - "add_date": "2025-09-15T14:50:54.166449+01:00", - "views": 28, - "media_type": "video", - "state": "public", - "duration": 13, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/654e4ca525ea4a979ef0065f9991f335_yCPofZH.VID_20230917_094453.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/654e4ca525ea4a979ef0065f9991f335.tmpzwnlnlun.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "35.0MB" - }, - { - "friendly_token": "meivs1H3R", - "url": "https://videojs.mediacms.io/view?m=meivs1H3R", - "api_url": "https://videojs.mediacms.io/api/v1/media/meivs1H3R", - "user": "markos", - "title": "video.mp4", - "description": "", - "add_date": "2025-07-08T13:33:24+01:00", - "views": 107, - "media_type": "video", - "state": "public", - "duration": 7, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/d6ae9093cb1648529432f38ee1198200_8Bqn2pb.video.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/d6ae9093cb1648529432f38ee1198200.tmpshyvhjby.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "19.2MB" - }, - { - "friendly_token": "Q531pthDT", - "url": "https://videojs.mediacms.io/view?m=Q531pthDT", - "api_url": "https://videojs.mediacms.io/api/v1/media/Q531pthDT", - "user": "admin", - "title": "19224432hd_1920_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:22:59.568359+01:00", - "views": 16, - "media_type": "video", - "state": "public", - "duration": 24, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/743fbae69e3a421f9017b4b26f08f94a_wrABxwh.19224432hd_1920_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/743fbae69e3a421f9017b4b26f08f94a.tmp6gnt2iza.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "16.9MB" - }, - { - "friendly_token": "DjplF1kqz", - "url": "https://videojs.mediacms.io/view?m=DjplF1kqz", - "api_url": "https://videojs.mediacms.io/api/v1/media/DjplF1kqz", - "user": "admin", - "title": "19553130hd_1920_1080_30fps.mp4", - "description": "", - "add_date": "2025-10-01T15:23:04.080897+01:00", - "views": 9, - "media_type": "video", - "state": "public", - "duration": 9, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/9c8dc7b294394c8f8ad101556c6ca327_thTz43p.19553130hd_1920_1080_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/9c8dc7b294394c8f8ad101556c6ca327.tmps4d56664.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "6.4MB" - }, - { - "friendly_token": "lyNk0HYMx", - "url": "https://videojs.mediacms.io/view?m=lyNk0HYMx", - "api_url": "https://videojs.mediacms.io/api/v1/media/lyNk0HYMx", - "user": "admin", - "title": "16478029hd_1920_1080_24fps.mp4", - "description": "", - "add_date": "2025-10-01T15:22:51.462252+01:00", - "views": 7, - "media_type": "video", - "state": "public", - "duration": 14, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/82b779012c604afeadacfc3c3bdba584_B9yXEMI.16478029hd_1920_1080_24fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/82b779012c604afeadacfc3c3bdba584.tmp226vuafd.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "10.1MB" - }, - { - "friendly_token": "4NxnfB7F8", - "url": "https://videojs.mediacms.io/view?m=4NxnfB7F8", - "api_url": "https://videojs.mediacms.io/api/v1/media/4NxnfB7F8", - "user": "admin", - "title": "4193130hd_1922_1080_24fps.mp4", - "description": "", - "add_date": "2025-09-30T15:16:06.506083+01:00", - "views": 10, - "media_type": "video", - "state": "public", - "duration": 44, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/admin/96cb2b54607642b6877f309dad8926db_RTfRILY.4193130hd_1922_1080_24fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/admin/96cb2b54607642b6877f309dad8926db.tmp72yep0r5.gif", - "author_name": "admin", - "author_profile": "https://videojs.mediacms.io/user/admin/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos_6FncSBT.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "30.9MB" - }, - { - "friendly_token": "KWNEepos7", - "url": "https://videojs.mediacms.io/view?m=KWNEepos7", - "api_url": "https://videojs.mediacms.io/api/v1/media/KWNEepos7", - "user": "markos", - "title": "VID_20230813_104846.mp4", - "description": "", - "add_date": "2025-09-15T14:52:33.267086+01:00", - "views": 38, - "media_type": "video", - "state": "public", - "duration": 26, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/eb69a038fe4c4fbaa95752de95f31605_MrtO8cw.VID_20230813_104846.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/eb69a038fe4c4fbaa95752de95f31605.tmp4wl8jpje.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 2, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "66.4MB" - }, - { - "friendly_token": "UtRFqDxc8", - "url": "https://videojs.mediacms.io/view?m=UtRFqDxc8", - "api_url": "https://videojs.mediacms.io/api/v1/media/UtRFqDxc8", - "user": "markos", - "title": "VID_20220206_123853.mp4", - "description": "", - "add_date": "2025-09-15T14:53:30.537614+01:00", - "views": 32, - "media_type": "video", - "state": "public", - "duration": 15, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/markos/540d03d3a30248448034c018400dd16d_0nHBsiZ.VID_20220206_123853.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/markos/540d03d3a30248448034c018400dd16d.tmpe0s2dtk1.gif", - "author_name": "Markos", - "author_profile": "https://videojs.mediacms.io/user/markos/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/2025/09/23/markos.jpeg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "39.6MB" - }, - { - "friendly_token": "bMw0ZOVDc", - "url": "https://videojs.mediacms.io/view?m=bMw0ZOVDc", - "api_url": "https://videojs.mediacms.io/api/v1/media/bMw0ZOVDc", - "user": "thorkildjensen", - "title": "14060819_3840_2160_30fps.mp4", - "description": "Jump in timeline via link in description: 00:05", - "add_date": "2025-09-22T08:24:54+01:00", - "views": 52, - "media_type": "video", - "state": "public", - "duration": 11, - "thumbnail_url": "https://videojs.mediacms.io/media/original/thumbnails/user/thorkildjensen/fea7bb6a434d4e43b98ec4f2bf1389a2_izGw7ow.14060819_3840_2160_30fps.mp4.jpg", - "is_reviewed": true, - "preview_url": "/media/encoded/1/thorkildjensen/fea7bb6a434d4e43b98ec4f2bf1389a2.tmp4y3qxrlh.gif", - "author_name": "Thorkild Jensen", - "author_profile": "https://videojs.mediacms.io/user/thorkildjensen/", - "author_thumbnail": "https://videojs.mediacms.io/media/userlogos/user.jpg", - "encoding_status": "success", - "likes": 1, - "dislikes": 0, - "reported_times": 0, - "featured": false, - "user_featured": false, - "size": "31.7MB" - } - ] + "related_media": [] } diff --git a/frontend-tools/video-js/src/components/overlays/EndScreenOverlay.js b/frontend-tools/video-js/src/components/overlays/EndScreenOverlay.js index 034ac015..523bd9b3 100644 --- a/frontend-tools/video-js/src/components/overlays/EndScreenOverlay.js +++ b/frontend-tools/video-js/src/components/overlays/EndScreenOverlay.js @@ -45,7 +45,7 @@ class EndScreenOverlay extends Component { } createGrid() { - const { columns, maxVideos, useSwiper } = this.getGridConfig(); + const { columns, maxVideos, useSwiper, itemsPerView, gridRows } = this.getGridConfig(); // Get videos to show - access directly from options during createEl const relatedVideos = this.options_?.relatedVideos || this.relatedVideos || []; @@ -55,7 +55,7 @@ class EndScreenOverlay extends Component { : this.createSampleVideos().slice(0, maxVideos); if (useSwiper) { - return this.createSwiperGrid(videosToShow); + return this.createSwiperGrid(videosToShow, itemsPerView || 2, columns, gridRows || 1); } else { return this.createRegularGrid(columns, videosToShow); } @@ -91,14 +91,14 @@ class EndScreenOverlay extends Component { return grid; } - createSwiperGrid(videosToShow) { + createSwiperGrid(videosToShow, itemsPerView = 2, columns = 2, gridRows = 1) { const container = videojs.dom.createEl('div', { className: 'vjs-related-videos-swiper-container', }); // Container styling - ensure it stays within bounds container.style.position = 'relative'; - container.style.padding = '20px'; + container.style.padding = gridRows > 1 ? '12px' : '20px'; // Minimal padding for 2x2 grid container.style.height = '100%'; container.style.width = '100%'; container.style.display = 'flex'; @@ -111,16 +111,32 @@ class EndScreenOverlay extends Component { className: 'vjs-related-videos-swiper', }); - swiperWrapper.style.display = 'flex'; - swiperWrapper.style.overflowX = 'auto'; - swiperWrapper.style.overflowY = 'hidden'; - swiperWrapper.style.gap = '12px'; - swiperWrapper.style.paddingBottom = '10px'; - swiperWrapper.style.scrollBehavior = 'smooth'; - swiperWrapper.style.scrollSnapType = 'x mandatory'; - swiperWrapper.style.width = '100%'; - swiperWrapper.style.maxWidth = '100%'; - swiperWrapper.style.boxSizing = 'border-box'; + if (gridRows > 1) { + // Multi-row grid layout (e.g., 2x2 for landscape) + swiperWrapper.style.display = 'flex'; + swiperWrapper.style.overflowX = 'auto'; + swiperWrapper.style.overflowY = 'hidden'; + swiperWrapper.style.scrollBehavior = 'smooth'; + swiperWrapper.style.scrollSnapType = 'x mandatory'; + swiperWrapper.style.width = '100%'; + swiperWrapper.style.maxWidth = '100%'; + swiperWrapper.style.height = '100%'; + swiperWrapper.style.flex = '1'; + swiperWrapper.style.boxSizing = 'border-box'; + swiperWrapper.style.gap = '0'; // Remove gap, we'll handle it in pages + } else { + // Single row layout (original swiper) + swiperWrapper.style.display = 'flex'; + swiperWrapper.style.overflowX = 'auto'; + swiperWrapper.style.overflowY = 'hidden'; + swiperWrapper.style.gap = '12px'; + swiperWrapper.style.paddingBottom = '10px'; + swiperWrapper.style.scrollBehavior = 'smooth'; + swiperWrapper.style.scrollSnapType = 'x mandatory'; + swiperWrapper.style.width = '100%'; + swiperWrapper.style.maxWidth = '100%'; + swiperWrapper.style.boxSizing = 'border-box'; + } // Hide scrollbar and prevent scroll propagation swiperWrapper.style.scrollbarWidth = 'none'; // Firefox @@ -158,17 +174,56 @@ class EndScreenOverlay extends Component { { passive: true } ); - // Create video items for swiper (show 2 at a time, but allow scrolling through all) - videosToShow.forEach((video) => { - const videoItem = this.createVideoItem(video, true); // Pass true for swiper mode - swiperWrapper.appendChild(videoItem); - }); + if (gridRows > 1) { + // Create pages with grid layout (e.g., 2x2 grid per page) + const itemsPerPage = itemsPerView; + const totalPages = Math.ceil(videosToShow.length / itemsPerPage); + + for (let pageIndex = 0; pageIndex < totalPages; pageIndex++) { + const page = videojs.dom.createEl('div', { + className: 'vjs-swiper-page', + }); + + page.style.minWidth = '100%'; + page.style.width = '100%'; + page.style.height = '100%'; + page.style.display = 'grid'; + page.style.gridTemplateColumns = `repeat(${columns}, 1fr)`; + page.style.gridTemplateRows = `repeat(${gridRows}, 1fr)`; + page.style.gap = '12px'; // Increased gap for better spacing + page.style.scrollSnapAlign = 'start'; + page.style.boxSizing = 'border-box'; + page.style.alignContent = 'stretch'; + page.style.justifyContent = 'stretch'; + page.style.alignItems = 'stretch'; + page.style.justifyItems = 'stretch'; + + // Get videos for this page + const startIndex = pageIndex * itemsPerPage; + const endIndex = Math.min(startIndex + itemsPerPage, videosToShow.length); + const pageVideos = videosToShow.slice(startIndex, endIndex); + + // Create video items for this page + pageVideos.forEach((video) => { + const videoItem = this.createVideoItem(video, true, itemsPerView, true); // Pass true for grid mode + page.appendChild(videoItem); + }); + + swiperWrapper.appendChild(page); + } + } else { + // Single row - create video items directly + videosToShow.forEach((video) => { + const videoItem = this.createVideoItem(video, true, itemsPerView, false); + swiperWrapper.appendChild(videoItem); + }); + } container.appendChild(swiperWrapper); - // Add navigation indicators if there are more than 2 videos - if (videosToShow.length > 2) { - const indicators = this.createSwiperIndicators(videosToShow.length, swiperWrapper); + // Add navigation indicators if there are more videos than can fit in one view + if (videosToShow.length > itemsPerView) { + const indicators = this.createSwiperIndicators(videosToShow.length, swiperWrapper, itemsPerView); container.appendChild(indicators); } @@ -190,10 +245,48 @@ class EndScreenOverlay extends Component { // Calculate maximum rows that can fit - be more aggressive const maxRows = Math.max(2, Math.floor((availableHeight + gap) / (cardHeight + gap))); - console.log('Grid Config:', { playerWidth, playerHeight, availableHeight, maxRows }); + // Detect landscape orientation on mobile + // Check screen/window orientation first, then player dimensions + const screenWidth = window.innerWidth || document.documentElement.clientWidth; + const screenHeight = window.innerHeight || document.documentElement.clientHeight; + const isScreenLandscape = screenWidth > screenHeight; + + const isLandscape = playerWidth > playerHeight; + + // Detect mobile/touch devices - should always show swiper + // Check both width and touch capability for better detection + const isTouchDevice = this.isTouchDevice; + const isSmallScreen = screenWidth < 700 || playerWidth < 700; + const isMobileOrTouch = isTouchDevice || isSmallScreen; + + // For mobile, prioritize screen orientation over player dimensions + // Only consider it landscape if BOTH screen and player are in landscape + const isDefinitelyLandscape = isMobileOrTouch ? isScreenLandscape && isLandscape : isLandscape; + + console.log('Grid Config:', { + screenWidth, + screenHeight, + isScreenLandscape, + playerWidth, + playerHeight, + availableHeight, + maxRows, + isLandscape, + isDefinitelyLandscape, + isTouchDevice, + isSmallScreen, + isMobileOrTouch, + }); // Enhanced grid configuration to fill all available space - if (playerWidth >= 1600) { + // Check mobile/touch conditions first - swiper should ALWAYS be used on mobile/touch devices + if (isMobileOrTouch && isDefinitelyLandscape) { + // Mobile/Touch landscape: show 2x2 grid (4 items total) with swiper for pagination + return { columns: 2, maxVideos: 12, useSwiper: true, itemsPerView: 4, gridRows: 2 }; + } else if (isMobileOrTouch) { + // Mobile/Touch portrait: show 2 items in single row swiper mode + return { columns: 2, maxVideos: 12, useSwiper: true, itemsPerView: 2, gridRows: 1 }; + } else if (playerWidth >= 1600) { const columns = 5; return { columns, maxVideos: columns * maxRows, useSwiper: false }; // Fill all available rows } else if (playerWidth >= 1200) { @@ -202,11 +295,9 @@ class EndScreenOverlay extends Component { } else if (playerWidth >= 900) { const columns = 3; return { columns, maxVideos: columns * maxRows, useSwiper: false }; // Fill all available rows - } else if (playerWidth >= 700) { + } else { const columns = 2; return { columns, maxVideos: columns * maxRows, useSwiper: false }; // Fill all available rows - } else { - return { columns: 2, maxVideos: 12, useSwiper: true }; // Use swiper for small screens } } @@ -220,7 +311,7 @@ class EndScreenOverlay extends Component { return this.createSampleVideos().slice(0, maxVideos); } - createVideoItem(video, isSwiperMode = false) { + createVideoItem(video, isSwiperMode = false, itemsPerView = 2, isGridMode = false) { const item = videojs.dom.createEl('div', { className: `vjs-related-video-item ${isSwiperMode ? 'vjs-swiper-item' : ''}`, }); @@ -228,7 +319,7 @@ class EndScreenOverlay extends Component { // Consistent item styling with fixed dimensions item.style.position = 'relative'; item.style.backgroundColor = '#1a1a1a'; - item.style.borderRadius = '6px'; + item.style.borderRadius = '8px'; item.style.overflow = 'hidden'; item.style.cursor = 'pointer'; item.style.transition = 'transform 0.15s ease, box-shadow 0.15s ease'; @@ -236,11 +327,21 @@ class EndScreenOverlay extends Component { item.style.flexDirection = 'column'; // Consistent dimensions for all cards - if (isSwiperMode) { - // Calculate proper width for swiper items (2 items visible + gap) - item.style.minWidth = 'calc(50% - 6px)'; // 50% width minus half the gap - item.style.width = 'calc(50% - 6px)'; - item.style.maxWidth = '180px'; // Maximum width for larger screens + if (isGridMode) { + // Grid mode (2x2): items fill their grid cell completely + item.style.height = '100%'; + item.style.minHeight = '0'; + item.style.width = '100%'; + item.style.maxWidth = 'none'; + item.style.flex = '1'; + } else if (isSwiperMode) { + // Single row swiper mode: calculate width based on items per view + // Formula: (100% / itemsPerView) - (gap * (itemsPerView - 1) / itemsPerView) + const itemsPerRow = itemsPerView / (itemsPerView === 4 ? 2 : 1); // For 4 items in 2 rows, show 2 per row + const gapAdjustment = (12 * (itemsPerRow - 1)) / itemsPerRow; + item.style.minWidth = `calc(${100 / itemsPerRow}% - ${gapAdjustment}px)`; + item.style.width = `calc(${100 / itemsPerRow}% - ${gapAdjustment}px)`; + item.style.maxWidth = itemsPerView === 4 ? '150px' : '180px'; // Smaller max width for 4 items // Simpler height since text is overlaid on thumbnail const cardHeight = '120px'; // Just the thumbnail height @@ -270,7 +371,7 @@ class EndScreenOverlay extends Component { } // Create thumbnail container with overlaid text - const thumbnailContainer = this.createThumbnailWithOverlay(video, isSwiperMode); + const thumbnailContainer = this.createThumbnailWithOverlay(video, isSwiperMode, itemsPerView); item.appendChild(thumbnailContainer); console.log('Created video item with overlay:', item); @@ -331,7 +432,7 @@ class EndScreenOverlay extends Component { return container; } - createThumbnailWithOverlay(video, isSwiperMode = false) { + createThumbnailWithOverlay(video, isSwiperMode = false, itemsPerView = 2) { const container = videojs.dom.createEl('div', { className: 'vjs-related-video-thumbnail-container', }); @@ -339,9 +440,13 @@ class EndScreenOverlay extends Component { // Container styling - full height since it contains everything container.style.position = 'relative'; container.style.width = '100%'; - container.style.height = '120px'; + container.style.height = '100%'; + container.style.minHeight = '120px'; container.style.overflow = 'hidden'; - container.style.borderRadius = '6px'; + container.style.borderRadius = '8px'; + container.style.flex = '1'; + container.style.display = 'flex'; + container.style.flexDirection = 'column'; // Create thumbnail image const thumbnail = videojs.dom.createEl('img', { @@ -354,6 +459,9 @@ class EndScreenOverlay extends Component { thumbnail.style.height = '100%'; thumbnail.style.objectFit = 'cover'; thumbnail.style.display = 'block'; + thumbnail.style.flex = '1'; + thumbnail.style.minWidth = '0'; + thumbnail.style.minHeight = '0'; container.appendChild(thumbnail); @@ -370,7 +478,7 @@ class EndScreenOverlay extends Component { duration.style.color = 'white'; duration.style.padding = '2px 6px'; duration.style.borderRadius = '3px'; - duration.style.fontSize = '11px'; + duration.style.fontSize = itemsPerView === 4 ? '10px' : '11px'; duration.style.fontWeight = '600'; duration.style.lineHeight = '1'; duration.style.zIndex = '3'; @@ -384,12 +492,12 @@ class EndScreenOverlay extends Component { }); textOverlay.style.position = 'absolute'; - textOverlay.style.top = '8px'; - textOverlay.style.left = '8px'; - textOverlay.style.right = '8px'; + textOverlay.style.top = itemsPerView === 4 ? '6px' : '8px'; + textOverlay.style.left = itemsPerView === 4 ? '6px' : '8px'; + textOverlay.style.right = itemsPerView === 4 ? '6px' : '8px'; textOverlay.style.background = 'linear-gradient(to bottom, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.4) 70%, transparent 100%)'; - textOverlay.style.padding = '8px'; + textOverlay.style.padding = itemsPerView === 4 ? '6px' : '8px'; textOverlay.style.borderRadius = '4px'; textOverlay.style.zIndex = '2'; @@ -399,10 +507,11 @@ class EndScreenOverlay extends Component { }); title.textContent = video.title || 'Sample Video Title'; title.style.color = '#ffffff'; - title.style.fontSize = isSwiperMode ? '12px' : '13px'; + // Adjust font sizes based on items per view + title.style.fontSize = itemsPerView === 4 ? '11px' : isSwiperMode ? '12px' : '13px'; title.style.fontWeight = '600'; title.style.lineHeight = '1.3'; - title.style.marginBottom = '4px'; + title.style.marginBottom = itemsPerView === 4 ? '3px' : '4px'; title.style.overflow = 'hidden'; title.style.textOverflow = 'ellipsis'; title.style.display = '-webkit-box'; @@ -428,7 +537,8 @@ class EndScreenOverlay extends Component { meta.textContent = metaText; meta.style.color = '#e0e0e0'; - meta.style.fontSize = isSwiperMode ? '10px' : '11px'; + // Adjust font sizes based on items per view + meta.style.fontSize = itemsPerView === 4 ? '9px' : isSwiperMode ? '10px' : '11px'; meta.style.lineHeight = '1.2'; meta.style.overflow = 'hidden'; meta.style.textOverflow = 'ellipsis'; @@ -529,7 +639,7 @@ class EndScreenOverlay extends Component { return info; } - createSwiperIndicators(totalVideos, swiperWrapper) { + createSwiperIndicators(totalVideos, swiperWrapper, itemsPerView = 2) { const indicators = videojs.dom.createEl('div', { className: 'vjs-swiper-indicators', }); @@ -539,7 +649,6 @@ class EndScreenOverlay extends Component { indicators.style.gap = '8px'; indicators.style.marginTop = '10px'; - const itemsPerView = 2; const totalPages = Math.ceil(totalVideos / itemsPerView); for (let i = 0; i < totalPages; i++) { diff --git a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx index 43c919dc..ff758b6c 100644 --- a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx +++ b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx @@ -208,1111 +208,14 @@ function VideoJSPlayer({ videoId = 'default-video' }) { isPlayList: false, previewSprite: { url: sampleMediaData.sprites_url - ? 'https://videojs.mediacms.io' + sampleMediaData.sprites_url - : 'https://videojs.mediacms.io/media/original/thumbnails/user/admin/43cc73a8c1604425b7057ad2b50b1798.19247660hd_1920_1080_60fps.mp4sprites.jpg', + ? 'https://deic.mediacms.io' + sampleMediaData.sprites_url + : 'https://deic.mediacms.io/media/original/thumbnails/user/admin/43cc73a8c1604425b7057ad2b50b1798.19247660hd_1920_1080_60fps.mp4sprites.jpg', frame: { width: 160, height: 90, seconds: 10 }, }, - siteUrl: 'https://videojs.mediacms.io', - nextLink: 'https://videojs.mediacms.io/view?m=elygiagorgechania', + siteUrl: 'https://deic.mediacms.io', + nextLink: 'https://deic.mediacms.io/view?m=elygiagorgechania', urlAutoplay: true, urlMuted: false, - - // FALLBACK - keep old structure for reference - __data_old: { - // COMMON - title: 'Modi tempora est quaerat numquam', - author_name: 'Markos Gogoulos', - author_profile: '/user/markos/', - author_thumbnail: '/media/userlogos/user.jpg', - url: 'https://videojs.mediacms.io/view?m=2Uk08Il5u', - poster_url: '', - __poster_url: - '/media/original/thumbnails/user/markos/db52140de7204022a1e5f08e078b4ec6_VKPTF4v.UniversityofCopenhagenMærskTower.mp4.jpg', - ___chapter_data: [], - chapter_data: [ - { - startTime: '00:00:00.000', - endTime: '00:00:02.295', - chapterTitle: 'A1 Lorem ipsum dolor sit amet consectetur adipisicing elit.', - }, - { startTime: '00:00:02.295', endTime: '00:00:04.590', chapterTitle: 'A2 of Marine Life' }, - { - startTime: '00:00:04.590', - endTime: '00:00:06.885', - chapterTitle: 'A3 Reef Ecosystems', - }, - { - startTime: '00:00:06.885', - endTime: '00:00:09.180', - chapterTitle: 'A4 Coral Formation and Growth', - }, - { - startTime: '00:00:09.180', - endTime: '00:00:11.475', - chapterTitle: 'A5 Tropical Fish Species', - }, - { - startTime: '00:00:11.475', - endTime: '00:00:13.770', - chapterTitle: 'A6 Ocean Current Patterns', - }, - { - startTime: '00:00:13.770', - endTime: '00:00:16.065', - chapterTitle: 'A7 Deep Sea Exploration', - }, - { - startTime: '00:00:16.065', - endTime: '00:00:18.360', - chapterTitle: 'A8 Marine Conservation Efforts', - }, - { - startTime: '00:00:18.360', - endTime: '00:00:20.655', - chapterTitle: 'A9 Underwater Photography Techniques', - }, - { - startTime: '00:00:20.655', - endTime: '00:00:22.950', - chapterTitle: 'A10 Plankton and Microscopic Life', - }, - { - startTime: '00:00:22.950', - endTime: '00:00:25.245', - chapterTitle: 'A11 Whale Migration Routes', - }, - { - startTime: '00:00:25.245', - endTime: '00:00:27.540', - chapterTitle: 'A12 Tidal Pool Ecosystems', - }, - { - startTime: '00:00:27.540', - endTime: '00:00:29.835', - chapterTitle: 'A13 Submarine Technology', - }, - { - startTime: '00:00:29.835', - endTime: '00:00:32.130', - chapterTitle: 'A14 Ocean Pollution Impact', - }, - { - startTime: '00:00:32.130', - endTime: '00:00:34.425', - chapterTitle: 'A15 Bioluminescent Creatures', - }, - { - startTime: '00:00:34.425', - endTime: '00:00:36.720', - chapterTitle: 'A16 Seaweed and Kelp Forests', - }, - { - startTime: '00:00:36.720', - endTime: '00:00:39.015', - chapterTitle: 'A17 Marine Food Chain Dynamics', - }, - { - startTime: '00:00:39.015', - endTime: '00:00:41.310', - chapterTitle: 'A18 Coastal Erosion and Climate Change', - }, - ], - related_media: [ - { - friendly_token: 'dktSm7iEo', - url: 'https://videojs.mediacms.io/view?m=dktSm7iEo', - api_url: 'https://videojs.mediacms.io/api/v1/media/dktSm7iEo', - user: 'markos', - title: 'Sed aliquam consectetur dolor.', - description: - 'Voluptatem quiquia dolorem labore dolore. Dolor etincidunt non etincidunt etincidunt sed. Adipisci eius etincidunt dolor magnam dolor. Dolorem porro etincidunt quaerat. Eius magnam dolorem tempora voluptatem labore. Dolore sed porro ipsum aliquam numquam non dolor. Labore aliquam labore dolor sit quisquam quaerat.', - add_date: '2024-10-02T05:28:18.784775-04:00', - views: 803, - media_type: 'video', - state: 'public', - duration: 12, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/8624c4080afc46eba8b4f27a81eccf27.Birch.mp4_myELKan.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/8624c4080afc46eba8b4f27a81eccf27.tmpb7kerjb2.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: '124.5MB', - }, - { - friendly_token: 'zK2nirNLC', - url: 'https://demo.mediacms.io/view?m=zK2nirNLC', - api_url: 'https://demo.mediacms.io/api/v1/media/zK2nirNLC', - user: 'markos', - title: 'University of Copenhagen Mærsk Tower', - description: 'https://maps.app.goo.gl/ewVAGgqdrb1MD1sF7', - add_date: '2025-06-06T00:00:00-04:00', - views: 632, - media_type: 'video', - state: 'public', - duration: 27, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/6497e960081b4b8abddcf4cbdf2bf4eb_38hpsj6.20250604_080632.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/6497e960081b4b8abddcf4cbdf2bf4eb.tmpjc3_yx1g.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: '58.8MB', - }, - { - friendly_token: 'o7lKzt664', - url: 'https://demo.mediacms.io/view?m=o7lKzt664', - api_url: 'https://demo.mediacms.io/api/v1/media/o7lKzt664', - user: 'markos', - title: 'Magnam velit ipsum quisquam amet magnam etincidunt.', - description: - 'Magnam sed quisquam quiquia dolor est. Tempora sit etincidunt dolor dolore magnam. Numquam non dolorem eius aliquam non. Consectetur sit consectetur dolor quaerat est. Consectetur amet dolor ut dolor ipsum. Mpla mpla antalya', - add_date: '2024-10-02T05:35:10-04:00', - views: 1378, - media_type: 'video', - state: 'public', - duration: 6, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/95eb092b57c24f52b75691fa382d16bb_Bg99UmX.20240526_123312.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/95eb092b57c24f52b75691fa382d16bb.tmpthrejon6.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 22, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: '13.0MB', - }, - { - friendly_token: 'mFELnYWko', - url: 'https://demo.mediacms.io/view?m=mFELnYWko', - api_url: 'https://demo.mediacms.io/api/v1/media/mFELnYWko', - user: 'markos', - title: 'kubectl-cheat-sheet.pdf', - description: '', - add_date: '2024-10-25T04:24:39-04:00', - views: 1391, - media_type: 'pdf', - state: 'public', - duration: 0, - thumbnail_url: null, - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 15, - dislikes: 9, - reported_times: 1, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'ZLjVzLcCE', - url: 'https://demo.mediacms.io/view?m=ZLjVzLcCE', - api_url: 'https://demo.mediacms.io/api/v1/media/ZLjVzLcCE', - user: 'markos', - title: 'Quaerat velit sed numquam ipsum magnam.', - description: - 'Dolore numquam aliquam dolore modi modi. Dolor quaerat est voluptatem ut. Dolor eius tempora magnam etincidunt ipsum modi porro. Etincidunt consectetur est est sed ut. Porro neque sed dolorem dolore. Sed velit quisquam ipsum quisquam consectetur porro.', - add_date: '2024-10-02T05:34:03.836032-04:00', - views: 888, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/b5e8dea6a0a3477885db786f2e89fb51.IMG_20240324_141309.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'bvMsRGRxE', - url: 'https://demo.mediacms.io/view?m=bvMsRGRxE', - api_url: 'https://demo.mediacms.io/api/v1/media/bvMsRGRxE', - user: 'markos', - title: 'Numquam quisquam amet dolore quisquam ipsum ut.', - description: - 'Modi numquam magnam numquam eius labore est dolorem. Voluptatem etincidunt neque ipsum non. Non tempora etincidunt magnam etincidunt. Sed dolor dolore amet quiquia porro sit non. Tempora etincidunt modi sed etincidunt est aliquam. Magnam aliquam ipsum modi dolore. Etincidunt sit eius dolore sed neque porro labore. Eius etincidunt dolorem est quiquia amet aliquam. Quaerat velit labore est dolor.', - add_date: '2024-10-02T05:33:02.972212-04:00', - views: 773, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/b9717b02cd8b45ec91d07470933810db.IMG_20231226_140530.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 10, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'lsNWKKq5N', - url: 'https://demo.mediacms.io/view?m=lsNWKKq5N', - api_url: 'https://demo.mediacms.io/api/v1/media/lsNWKKq5N', - user: 'markos', - title: 'Quaerat quaerat numquam porro dolor', - description: - 'Modi dolorem non non neque dolor magnam quisquam. Magnam amet magnam porro. Dolorem quiquia dolorem etincidunt labore ipsum aliquam sed. Eius sed eius sit consectetur quaerat. Voluptatem dolorem porro etincidunt labore aliquam quisquam. Adipisci quisquam dolorem dolorem magnam dolorem ipsum. Consectetur quaerat magnam sit voluptatem.', - add_date: '2024-10-02T00:00:00-04:00', - views: 666, - media_type: 'video', - state: 'public', - duration: 13, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/58008fdc69d34c229a85f29076004639.VID_20230917_094453.mp4_Pe8a1dv.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/58008fdc69d34c229a85f29076004639.tmp85b478_u.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 10, - dislikes: 3, - reported_times: 1, - featured: true, - user_featured: false, - size: '35.0MB', - }, - { - friendly_token: 'tsgNaSe6E', - url: 'https://demo.mediacms.io/view?m=tsgNaSe6E', - api_url: 'https://demo.mediacms.io/api/v1/media/tsgNaSe6E', - user: 'markos', - title: 'Magnam ipsum eius numquam quiquia non adipisci.', - description: - 'Adipisci labore dolorem ipsum quaerat non dolore ut. Velit porro neque non consectetur neque neque. Ut sit tempora tempora. Ipsum ut velit neque. Quaerat labore amet porro porro amet tempora. Sed voluptatem est amet quisquam sed numquam velit. Est ipsum non labore. Consectetur amet neque consectetur dolor ipsum.', - add_date: '2024-10-02T05:32:46.253917-04:00', - views: 824, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/0405f61e131f431793644be3742fcc1a.20240628_235522.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 12, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'f9xqzbbJE', - url: 'https://demo.mediacms.io/view?m=f9xqzbbJE', - api_url: 'https://demo.mediacms.io/api/v1/media/f9xqzbbJE', - user: 'markos', - title: 'Magnam quaerat numquam modi dolore sed amet.', - description: - 'Non non voluptatem neque velit labore. Eius labore non aliquam quisquam adipisci neque. Aliquam ipsum sed ipsum quisquam. Sit quaerat sed dolore non tempora. Ipsum sed labore dolore consectetur. Modi non quisquam sed ut ut dolor quaerat.', - add_date: '2024-10-02T05:34:18.498303-04:00', - views: 844, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/369f44b14f944941881a20e8d5285e78.IMG_20240324_151737.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 3, - dislikes: 1, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'DE3KByBeo', - url: 'https://demo.mediacms.io/view?m=DE3KByBeo', - api_url: 'https://demo.mediacms.io/api/v1/media/DE3KByBeo', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 272, - media_type: 'video', - state: 'public', - duration: 29, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/58b35efa3aca454196227c0eb5e2ca75_pkgSAK2.20250517_101207.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/58b35efa3aca454196227c0eb5e2ca75.tmpsw6vmsfo.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 2, - reported_times: 0, - featured: false, - user_featured: false, - size: '62.0MB', - }, - { - friendly_token: 'M8ktwf8kF', - url: 'https://demo.mediacms.io/view?m=M8ktwf8kF', - api_url: 'https://demo.mediacms.io/api/v1/media/M8ktwf8kF', - user: 'markos', - title: 'Quaerat voluptatem quisquam neque velit neque.', - description: - 'Aliquam ipsum quisquam dolor. Modi quisquam neque ut ipsum amet. Tempora quaerat ipsum aliquam velit velit porro est. Consectetur neque eius quisquam porro amet sit neque. Modi voluptatem neque modi. Ipsum aliquam labore quaerat.', - add_date: '2024-10-02T05:34:32.027708-04:00', - views: 852, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/48a682227b544388a1b547736668d0ad.IMG_20240324_151743.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 7, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 's2qAmRTJ9', - url: 'https://demo.mediacms.io/view?m=s2qAmRTJ9', - api_url: 'https://demo.mediacms.io/api/v1/media/s2qAmRTJ9', - user: 'markos', - title: 'Labore neque ipsum labore modi tempora aliquam neque.', - description: - 'Eius voluptatem aliquam sit sit ipsum consectetur. Dolorem velit amet modi. Porro quisquam velit neque dolorem. Dolorem modi quiquia aliquam. Numquam est magnam non numquam modi quisquam est. Sit velit ut labore sit dolore velit modi. Aliquam modi dolorem ut.', - add_date: '2024-10-02T05:34:27.197596-04:00', - views: 779, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/2b786916111947e3ba960d7146ae0424.IMG_20230708_133437.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: '8pWsxkOS5', - url: 'https://demo.mediacms.io/view?m=8pWsxkOS5', - api_url: 'https://demo.mediacms.io/api/v1/media/8pWsxkOS5', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 321, - media_type: 'video', - state: 'public', - duration: 47, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/d970760faf5745b4b3d0d0cff2b95d86_cvyjd5y.20250517_140535.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/d970760faf5745b4b3d0d0cff2b95d86.tmp3vtt3uip.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 5, - dislikes: 2, - reported_times: 0, - featured: false, - user_featured: false, - size: '101.2MB', - }, - { - friendly_token: 'swcx8A2h1', - url: 'https://demo.mediacms.io/view?m=swcx8A2h1', - api_url: 'https://demo.mediacms.io/api/v1/media/swcx8A2h1', - user: 'markos', - title: 'Etincidunt dolore eius ut non numquam dolore dolorem.', - description: - 'Etincidunt amet dolorem quisquam tempora. Dolorem dolor modi sit modi labore sit. Labore est sed non numquam. Porro non quaerat dolorem porro tempora sit. Ut neque est etincidunt velit eius. Etincidunt aliquam adipisci sed quiquia modi. Adipisci non sed adipisci velit.', - add_date: '2024-10-02T05:38:43-04:00', - views: 7973, - media_type: 'video', - state: 'public', - duration: 31, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/fe4933d67b884d4da507dd60e77f7438.VID_20200909_141053.mp4_bU90dbl.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/fe4933d67b884d4da507dd60e77f7438.tmpdd72kiwh.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 230, - dislikes: 62, - reported_times: 1, - featured: true, - user_featured: false, - size: '65.9MB', - }, - { - friendly_token: 'rNefa4WtV', - url: 'https://demo.mediacms.io/view?m=rNefa4WtV', - api_url: 'https://demo.mediacms.io/api/v1/media/rNefa4WtV', - user: 'markos', - title: 'Quaerat modi non eius.', - description: - 'Quisquam ut dolorem dolorem quisquam dolore. Non modi etincidunt labore sit quisquam. Sed neque quaerat quisquam voluptatem. Numquam labore neque etincidunt. Magnam etincidunt porro adipisci.', - add_date: '2024-10-02T05:36:46.062913-04:00', - views: 2683, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/ca0e3af507c64fc5995b9d97e4a8c779.20240527_091011.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 45, - dislikes: 16, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'LP09dv0mx', - url: 'https://demo.mediacms.io/view?m=LP09dv0mx', - api_url: 'https://demo.mediacms.io/api/v1/media/LP09dv0mx', - user: 'markos', - title: 'Est ipsum non etincidunt voluptatem adipisci labore.', - description: - 'Est sit voluptatem numquam ut etincidunt. Adipisci sed dolor voluptatem labore. Quiquia est sit eius eius labore velit. Tempora ut tempora neque. Ipsum eius sit labore amet dolorem non non. Quiquia velit amet eius sit ut ut voluptatem. Quiquia sit ut ipsum ipsum neque. Amet etincidunt aliquam consectetur voluptatem sed etincidunt quiquia. Sit eius dolore magnam sed velit consectetur. Etincidunt amet numquam sit porro.', - add_date: '2024-10-02T05:31:41.087014-04:00', - views: 711, - media_type: 'video', - state: 'public', - duration: 26, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/980decd203f245bbb3723cba73a94a11.VID_20230813_104846.mp4_3rwZtxQ.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/980decd203f245bbb3723cba73a94a11.tmpmddawiqe.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 11, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: '66.4MB', - }, - { - friendly_token: 'just_somethi', - url: 'https://demo.mediacms.io/view?m=just_somethi', - api_url: 'https://demo.mediacms.io/api/v1/media/just_somethi', - user: 'markos', - title: 'Sit consectetur dolore numquam.', - description: - 'Consectetur adipisci neque neque tempora. Amet quiquia ut labore non sit. Dolor aliquam quiquia adipisci dolor dolorem quiquia. Dolore porro modi labore quisquam adipisci numquam non. Dolor consectetur ut est neque.', - add_date: '2024-10-02T00:00:00-04:00', - views: 1288, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/7aaa65ac24224fe3a768aa6b7a723b58.20240527_090952.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 28, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'PbsYTGEol', - url: 'https://demo.mediacms.io/view?m=PbsYTGEol', - api_url: 'https://demo.mediacms.io/api/v1/media/PbsYTGEol', - user: 'markos', - title: 'Voluptatem porro neque tempora dolorem quiquia est dolor.', - description: - 'Labore aliquam dolorem quiquia est ipsum quiquia. Sed est amet non ipsum. Labore etincidunt etincidunt quiquia amet tempora tempora. Aliquam velit ipsum consectetur. Ipsum labore quaerat quiquia aliquam magnam. Quisquam ut velit velit dolorem dolorem. Aliquam quaerat tempora quisquam ut voluptatem voluptatem quiquia.', - add_date: '2024-10-02T05:33:48.024941-04:00', - views: 785, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/f01faaa2e7be4c9aa7598ab755898a09.IMG_20240324_141304.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 14, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'mkpfy31bY', - url: 'https://demo.mediacms.io/view?m=mkpfy31bY', - api_url: 'https://demo.mediacms.io/api/v1/media/mkpfy31bY', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 212, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/c2d40995ce7640e3b8cbfee1a2890c51.20250517_183010.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 2, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'w2lYWaW8e', - url: 'https://demo.mediacms.io/view?m=w2lYWaW8e', - api_url: 'https://demo.mediacms.io/api/v1/media/w2lYWaW8e', - user: 'markos', - title: 'Plane view approaching Copenhagen airport', - description: 'plane view', - add_date: '2025-06-06T00:00:00-04:00', - views: 664, - media_type: 'video', - state: 'public', - duration: 50, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/e84f1caf58f44d838456625ffe96173b_LQCWsAe.20250603_110810.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/e84f1caf58f44d838456625ffe96173b.tmp7hm26nok.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 3, - reported_times: 0, - featured: false, - user_featured: false, - size: '108.8MB', - }, - { - friendly_token: 'qLMrr970w', - url: 'https://demo.mediacms.io/view?m=qLMrr970w', - api_url: 'https://demo.mediacms.io/api/v1/media/qLMrr970w', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 215, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/558f53227cc5418c9b7d66a3740fe2f8.20250517_082340.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 2, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'elygiagorgechania', - url: 'https://demo.mediacms.io/view?m=elygiagorgechania', - api_url: 'https://demo.mediacms.io/api/v1/media/elygiagorgechania', - user: 'markos', - title: 'Exit of Elygia Gorge, Chania, Crete', - description: - 'This video is from the exit of Elygia Gorge, Chania, Crete, where it meets the sea!', - add_date: '2025-06-15T00:00:00-04:00', - views: 688, - media_type: 'video', - state: 'public', - duration: 29, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/c1ab03cab3bb46b5854a5e217cfe3013_Nete6ao.VID_20230813_144422.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/c1ab03cab3bb46b5854a5e217cfe3013.tmpjlxkhy0i.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: '75.6MB', - }, - { - friendly_token: 'OxO6BMVZb', - url: 'https://demo.mediacms.io/view?m=OxO6BMVZb', - api_url: 'https://demo.mediacms.io/api/v1/media/OxO6BMVZb', - user: 'markos', - title: 'Eius velit etincidunt amet tempora ut.', - description: - 'Aliquam eius adipisci adipisci. Quaerat dolor quaerat magnam. Amet ut quaerat sit sed magnam quaerat neque. Neque velit porro labore modi ut ut ut. Non quaerat consectetur dolor eius voluptatem. Quisquam modi amet sed magnam eius. Quisquam dolor dolore aliquam quisquam neque dolore. Quisquam dolor ut ipsum quiquia. Voluptatem quisquam neque quisquam quiquia adipisci. Est modi eius est etincidunt numquam quisquam ut.', - add_date: '2024-10-02T05:34:33.461809-04:00', - views: 1023, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/13299e6838e143fda776bacf7081484e.IMG_20230820_200357.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 4, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'hDHXkdwy0', - url: 'https://demo.mediacms.io/view?m=hDHXkdwy0', - api_url: 'https://demo.mediacms.io/api/v1/media/hDHXkdwy0', - user: 'markos', - title: 'Modi tempora est quaerat numquam', - description: - 'Magnam voluptatem est magnam dolorem. Etincidunt quiquia aliquam velit tempora porro. Magnam neque eius eius etincidunt ut ipsum. Adipisci labore quaerat modi. Ipsum modi quaerat consectetur est non quaerat sed. Neque ut modi adipisci dolore adipisci dolor ut. Dolor tempora adipisci quisquam. Dolorem consectetur velit adipisci etincidunt voluptatem. Non quisquam voluptatem adipisci. Voluptatem est aliquam porro labore non.', - add_date: '2024-10-02T05:36:42-04:00', - views: 1679, - media_type: 'video', - state: 'public', - duration: 24, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/a3c5642e13624149897f193981ebccf3.VID_20210307_111552.mp4_uEHcD0C.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/a3c5642e13624149897f193981ebccf3.tmpempjz6eh.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 32, - dislikes: 12, - reported_times: 0, - featured: true, - user_featured: false, - size: '52.4MB', - }, - { - friendly_token: 'vDKrrkIVc', - url: 'https://demo.mediacms.io/view?m=vDKrrkIVc', - api_url: 'https://demo.mediacms.io/api/v1/media/vDKrrkIVc', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 228, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/50f296fd588240d2ad80a6fb9a5ce7d6.20250518_093811.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 1, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: '4h3nsvXb1', - url: 'https://demo.mediacms.io/view?m=4h3nsvXb1', - api_url: 'https://demo.mediacms.io/api/v1/media/4h3nsvXb1', - user: 'markos', - title: 'Dolor voluptatem non quiquia consectetur est numquam sed.', - description: - 'Aliquam ipsum etincidunt neque ipsum. Consectetur ut non velit quaerat porro. Eius ut voluptatem velit aliquam dolor. Non etincidunt est quaerat quaerat. Quiquia est non ipsum numquam. Quisquam amet magnam sed eius quaerat. Magnam porro dolorem dolor. Numquam numquam quaerat est. Quisquam tempora ut quaerat est.', - add_date: '2024-10-02T05:32:43.865153-04:00', - views: 981, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/baca04d3009d4daba302919c25b4325e.IMG_1936.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 1, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'HdUU8boQP', - url: 'https://demo.mediacms.io/view?m=HdUU8boQP', - api_url: 'https://demo.mediacms.io/api/v1/media/HdUU8boQP', - user: 'markos', - title: 'Consectetur adipisci porro quiquia ipsum aliquam etincidunt ut.', - description: - 'Consectetur numquam eius amet est dolor neque modi. Consectetur est amet voluptatem quaerat numquam sed. Porro tempora ut ut. Non dolor amet sit. Labore porro neque dolorem numquam dolore ut. Modi sed adipisci dolore. Numquam magnam est tempora. Neque aliquam labore dolor ipsum porro.', - add_date: '2024-10-02T05:34:13.171233-04:00', - views: 795, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/e1df55b16b3b456ea88bf7feb7db6051.IMG_20230708_120717.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 8, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'vy5PTWJZ6', - url: 'https://demo.mediacms.io/view?m=vy5PTWJZ6', - api_url: 'https://demo.mediacms.io/api/v1/media/vy5PTWJZ6', - user: 'markos', - title: 'Non etincidunt numquam velit.', - description: - 'Etincidunt ut velit ipsum. Labore modi magnam eius quisquam. Dolorem magnam sit quiquia non dolorem tempora. Aliquam labore sed quaerat magnam est aliquam porro. Adipisci adipisci aliquam tempora ut aliquam eius amet. Est etincidunt quiquia dolorem amet consectetur. Ipsum neque dolorem dolore etincidunt.\r\n', - add_date: '2024-10-02T05:33:26-04:00', - views: 713, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/7a9ec6be9ce24a569a246c61d9b03690.IMG_20220528_135153.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 9, - dislikes: 1, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'TAdmfDUlu', - url: 'https://demo.mediacms.io/view?m=TAdmfDUlu', - api_url: 'https://demo.mediacms.io/api/v1/media/TAdmfDUlu', - user: 'markos', - title: 'Sed neque adipisci dolorem sed.', - description: - 'Quiquia ipsum velit amet. Consectetur porro numquam numquam magnam adipisci dolore. Dolor ipsum ut ut consectetur modi labore. Neque est non amet. Sit quiquia quisquam dolorem. Modi dolore modi dolorem ipsum ipsum. Neque modi modi dolorem quisquam numquam modi quaerat.\r\n\r\nbest scenes at 00:00:12 and 00:14', - add_date: '2024-10-02T00:00:00-04:00', - views: 821, - media_type: 'video', - state: 'public', - duration: 30, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/f371a6b2c157451d924bc4f612bf2667_Kh4GigX.Pexels_Videos_2079217_1.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/f371a6b2c157451d924bc4f612bf2667.tmp2jqxf9sr.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 20, - dislikes: 4, - reported_times: 0, - featured: true, - user_featured: false, - size: '90.0MB', - }, - { - friendly_token: 'kHd7EKAVH', - url: 'https://demo.mediacms.io/view?m=kHd7EKAVH', - api_url: 'https://demo.mediacms.io/api/v1/media/kHd7EKAVH', - user: 'markos', - title: 'Tempora magnam velit ipsum neque aliquam adipisci.', - description: - 'Porro dolorem eius sed non eius. Non dolor quiquia dolorem. Modi ut dolor aliquam dolor. Non est dolorem amet consectetur neque quiquia numquam. Aliquam adipisci quiquia voluptatem ipsum quisquam magnam adipisci. Sit adipisci dolor consectetur dolor quaerat. Magnam ut modi tempora. Modi non ipsum tempora etincidunt porro. Ut ut dolor ipsum non consectetur neque quiquia.', - add_date: '2024-10-02T05:33:57.651288-04:00', - views: 1051, - media_type: 'video', - state: 'public', - duration: 54, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/9d3b8425eb08400fa08d90f988bc5ff4.VID_20220821_110509.mp4_JzAol5C.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/9d3b8425eb08400fa08d90f988bc5ff4.tmpwlnjum5k.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 26, - dislikes: 8, - reported_times: 1, - featured: true, - user_featured: false, - size: '136.8MB', - }, - { - friendly_token: 'Otbc37Yj4', - url: 'https://demo.mediacms.io/view?m=Otbc37Yj4', - api_url: 'https://demo.mediacms.io/api/v1/media/Otbc37Yj4', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 311, - media_type: 'video', - state: 'public', - duration: 25, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/dd3af0e1dece43b490bbafc9400a407a_YtfxVr4.20250517_105515.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/dd3af0e1dece43b490bbafc9400a407a.tmpl3iqzl10.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 12, - dislikes: 1, - reported_times: 0, - featured: false, - user_featured: false, - size: '54.3MB', - }, - { - friendly_token: 'a1BP6J0fM', - url: 'https://demo.mediacms.io/view?m=a1BP6J0fM', - api_url: 'https://demo.mediacms.io/api/v1/media/a1BP6J0fM', - user: 'markos', - title: 'Velit sed magnam quiquia amet.', - description: - 'Numquam quiquia numquam ut etincidunt numquam. Dolore ut sit eius dolorem sed. Neque porro modi dolor ipsum amet dolore quisquam. Ipsum dolore dolor voluptatem eius quiquia etincidunt. Dolore etincidunt amet velit amet ipsum ut. Aliquam etincidunt consectetur est. Consectetur non quiquia voluptatem velit sed quisquam.', - add_date: '2024-10-02T05:35:15.434023-04:00', - views: 997, - media_type: 'video', - state: 'public', - duration: 11, - thumbnail_url: - 'https://videojs.mediacms.io/media/original/thumbnails/user/markos/db52140de7204022a1e5f08e078b4ec6_02xAHoZ.UniversityofCopenhagenMærskTower.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://videojs.mediacms.io/media/encoded/1/markos/db52140de7204022a1e5f08e078b4ec6.tmpuespp_ik.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://videojs.mediacms.io/user/markos/', - author_thumbnail: - 'https://videojs.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 14, - dislikes: 1, - reported_times: 0, - featured: true, - user_featured: false, - size: '3.5MB', - }, - ], - - // VIDEO - media_type: 'audio', - original_media_url: - '/media/original/user/markos/db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4', - hls_info: { - master_file: '/media/hls/5073e97457004961a163c5b504e2d7e8/master.m3u8', - '240_iframe': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-1/iframes.m3u8', - '480_iframe': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-2/iframes.m3u8', - '720_iframe': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-3/iframes.m3u8', - '144_iframe': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-4/iframes.m3u8', - '360_iframe': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-5/iframes.m3u8', - '240_playlist': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-1/stream.m3u8', - '480_playlist': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-2/stream.m3u8', - '720_playlist': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-3/stream.m3u8', - '144_playlist': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-4/stream.m3u8', - '360_playlist': '/media/hls/5073e97457004961a163c5b504e2d7e8/media-5/stream.m3u8', - }, - __hls_info: {}, - __encodings_info: {}, - encodings_info: { - 144: { - h264: { - title: 'h264-144', - url: '/media/encoded/23/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '0.9MB', - encoding_id: 84, - status: 'success', - }, - }, - 240: { - h264: { - title: 'h264-240', - url: '/media/encoded/2/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '1.7MB', - encoding_id: 85, - status: 'success', - }, - }, - 360: { - h264: { - title: 'h264-360', - url: '/media/encoded/3/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '2.9MB', - encoding_id: 86, - status: 'success', - }, - }, - 480: { - h264: { - title: 'h264-480', - url: '/media/encoded/13/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '4.5MB', - encoding_id: 87, - status: 'success', - }, - }, - 720: { - h264: { - title: 'h264-720', - url: '/media/encoded/10/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '8.3MB', - encoding_id: 88, - status: 'success', - }, - }, - 1080: { - h264: { - title: 'h264-1080', - url: '/media/encoded/7/markos/db52140de7204022a1e5f08e078b4ec6.db52140de7204022a1e5f08e078b4ec6.UniversityofCopenhagenMærskTower.mp4.mp4', - progress: 100, - size: '16.6MB', - encoding_id: 89, - status: 'success', - }, - }, - 1440: {}, - 2160: {}, - }, - - // AUDIO - /*media_type: 'audio', - original_media_url: - 'https://videojs.mediacms.io/media/original/user/markos/174be7a1ecb04850a6927a0af2887ccc.SizzlaHardGround.mp3', - hls_info: {}, - encodings_info: {},*/ - }, }, [] ); @@ -1821,7 +724,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) { const subtitleTracks = hasSubtitles ? backendSubtitles.map((track) => ({ kind: 'subtitles', - src: track.src, + src: (!isDevMode ? mediaData?.siteUrl : '') + track.src, srclang: track.srclang, label: track.label, default: track.default || false, @@ -2099,7 +1002,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) { // Use native text tracks on iOS for fullscreen caption support // On other devices, use Video.js text tracks for full CSS positioning control - nativeTextTracks: isIOS, + nativeTextTracks: isIOS && mediaData.data?.media_type !== 'audio' ? true : false, // Use native video tracks instead of emulated - disabled for consistency nativeVideoTracks: false, diff --git a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer__OLD.jsx b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer__OLD.jsx deleted file mode 100644 index 7720620d..00000000 --- a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer__OLD.jsx +++ /dev/null @@ -1,3334 +0,0 @@ -import React, { useEffect, useRef, useMemo } from 'react'; -import videojs from 'video.js'; -import 'video.js/dist/video-js.css'; -// import '../../VideoJS.css'; -import '../../styles/embed.css'; -//import '../controls/SubtitlesButton.css'; - -// Import the separated components -import EndScreenOverlay from '../overlays/EndScreenOverlay'; -import AutoplayCountdownOverlay from '../overlays/AutoplayCountdownOverlay'; -import EmbedInfoOverlay from '../overlays/EmbedInfoOverlay'; -import ChapterMarkers from '../markers/ChapterMarkers'; -import SpritePreview from '../markers/SpritePreview'; -import NextVideoButton from '../controls/NextVideoButton'; -import AutoplayToggleButton from '../controls/AutoplayToggleButton'; -import CustomRemainingTime from '../controls/CustomRemainingTime'; -import CustomChaptersOverlay from '../controls/CustomChaptersOverlay'; -import CustomSettingsMenu from '../controls/CustomSettingsMenu'; -import SeekIndicator from '../controls/SeekIndicator'; -import UserPreferences from '../../utils/UserPreferences'; - -function VideoJSPlayer({ videoId = 'default-video' }) { - const videoRef = useRef(null); - const playerRef = useRef(null); // Track the player instance - const userPreferences = useRef(new UserPreferences()); // User preferences instance - const customComponents = useRef({}); // Store custom components for cleanup - - // Check if this is an embed player (disable next video and autoplay features) - const isEmbedPlayer = videoId === 'video-embed'; - - // Utility function to detect touch devices - const isTouchDevice = useMemo(() => { - return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; - }, []); - - // Environment-based development mode configuration - const isDevMode = import.meta.env.VITE_DEV_MODE === 'true' || window.location.hostname.includes('vercel.app'); - // Safely access window.MEDIA_DATA with fallback using useMemo - const mediaData = useMemo( - () => - typeof window !== 'undefined' && window.MEDIA_DATA - ? window.MEDIA_DATA - : { - data: { - // COMMON - title: 'Modi tempora est quaerat numquam', - author_name: 'Markos Gogoulos', - author_profile: '/user/markos/', - author_thumbnail: '/media/userlogos/user.jpg', - url: 'https://videojs.mediacms.io/view?m=meivs1H3R', - poster_url: - '/media/original/thumbnails/user/markos/d6ae9093cb1648529432f38ee1198200_6BfyhyM.video.mp4.jpg', - - chapter_data: [ - { - startTime: '00:00:00.000', - endTime: '00:00:02.295', - chapterTitle: 'A1 Lorem ipsum dolor sit amet consectetur adipisicing elit.', - }, - { startTime: '00:00:02.295', endTime: '00:00:04.590', chapterTitle: 'A2 of Marine Life' }, - { - startTime: '00:00:04.590', - endTime: '00:00:06.885', - chapterTitle: 'A3 Reef Ecosystems', - }, - ], - related_media: [ - { - friendly_token: 'dktSm7iEo', - url: 'https://demo.mediacms.io/view?m=dktSm7iEo', - api_url: 'https://demo.mediacms.io/api/v1/media/dktSm7iEo', - user: 'markos', - title: 'Sed aliquam consectetur dolor.', - description: - 'Voluptatem quiquia dolorem labore dolore. Dolor etincidunt non etincidunt etincidunt sed. Adipisci eius etincidunt dolor magnam dolor. Dolorem porro etincidunt quaerat. Eius magnam dolorem tempora voluptatem labore. Dolore sed porro ipsum aliquam numquam non dolor. Labore aliquam labore dolor sit quisquam quaerat.', - add_date: '2024-10-02T05:28:18.784775-04:00', - views: 803, - media_type: 'video', - state: 'public', - duration: 12, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/8624c4080afc46eba8b4f27a81eccf27.Birch.mp4_myELKan.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/8624c4080afc46eba8b4f27a81eccf27.tmpb7kerjb2.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: '124.5MB', - }, - { - friendly_token: 'zK2nirNLC', - url: 'https://demo.mediacms.io/view?m=zK2nirNLC', - api_url: 'https://demo.mediacms.io/api/v1/media/zK2nirNLC', - user: 'markos', - title: 'University of Copenhagen Mærsk Tower', - description: 'https://maps.app.goo.gl/ewVAGgqdrb1MD1sF7', - add_date: '2025-06-06T00:00:00-04:00', - views: 632, - media_type: 'video', - state: 'public', - duration: 27, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/6497e960081b4b8abddcf4cbdf2bf4eb_38hpsj6.20250604_080632.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/6497e960081b4b8abddcf4cbdf2bf4eb.tmpjc3_yx1g.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: '58.8MB', - }, - { - friendly_token: 'o7lKzt664', - url: 'https://demo.mediacms.io/view?m=o7lKzt664', - api_url: 'https://demo.mediacms.io/api/v1/media/o7lKzt664', - user: 'markos', - title: 'Magnam velit ipsum quisquam amet magnam etincidunt.', - description: - 'Magnam sed quisquam quiquia dolor est. Tempora sit etincidunt dolor dolore magnam. Numquam non dolorem eius aliquam non. Consectetur sit consectetur dolor quaerat est. Consectetur amet dolor ut dolor ipsum. Mpla mpla antalya', - add_date: '2024-10-02T05:35:10-04:00', - views: 1378, - media_type: 'video', - state: 'public', - duration: 6, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/95eb092b57c24f52b75691fa382d16bb_Bg99UmX.20240526_123312.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/95eb092b57c24f52b75691fa382d16bb.tmpthrejon6.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 22, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: '13.0MB', - }, - { - friendly_token: 'mFELnYWko', - url: 'https://demo.mediacms.io/view?m=mFELnYWko', - api_url: 'https://demo.mediacms.io/api/v1/media/mFELnYWko', - user: 'markos', - title: 'kubectl-cheat-sheet.pdf', - description: '', - add_date: '2024-10-25T04:24:39-04:00', - views: 1391, - media_type: 'pdf', - state: 'public', - duration: 0, - thumbnail_url: null, - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 15, - dislikes: 9, - reported_times: 1, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'ZLjVzLcCE', - url: 'https://demo.mediacms.io/view?m=ZLjVzLcCE', - api_url: 'https://demo.mediacms.io/api/v1/media/ZLjVzLcCE', - user: 'markos', - title: 'Quaerat velit sed numquam ipsum magnam.', - description: - 'Dolore numquam aliquam dolore modi modi. Dolor quaerat est voluptatem ut. Dolor eius tempora magnam etincidunt ipsum modi porro. Etincidunt consectetur est est sed ut. Porro neque sed dolorem dolore. Sed velit quisquam ipsum quisquam consectetur porro.', - add_date: '2024-10-02T05:34:03.836032-04:00', - views: 888, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/b5e8dea6a0a3477885db786f2e89fb51.IMG_20240324_141309.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'bvMsRGRxE', - url: 'https://demo.mediacms.io/view?m=bvMsRGRxE', - api_url: 'https://demo.mediacms.io/api/v1/media/bvMsRGRxE', - user: 'markos', - title: 'Numquam quisquam amet dolore quisquam ipsum ut.', - description: - 'Modi numquam magnam numquam eius labore est dolorem. Voluptatem etincidunt neque ipsum non. Non tempora etincidunt magnam etincidunt. Sed dolor dolore amet quiquia porro sit non. Tempora etincidunt modi sed etincidunt est aliquam. Magnam aliquam ipsum modi dolore. Etincidunt sit eius dolore sed neque porro labore. Eius etincidunt dolorem est quiquia amet aliquam. Quaerat velit labore est dolor.', - add_date: '2024-10-02T05:33:02.972212-04:00', - views: 773, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/b9717b02cd8b45ec91d07470933810db.IMG_20231226_140530.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 10, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'lsNWKKq5N', - url: 'https://demo.mediacms.io/view?m=lsNWKKq5N', - api_url: 'https://demo.mediacms.io/api/v1/media/lsNWKKq5N', - user: 'markos', - title: 'Quaerat quaerat numquam porro dolor', - description: - 'Modi dolorem non non neque dolor magnam quisquam. Magnam amet magnam porro. Dolorem quiquia dolorem etincidunt labore ipsum aliquam sed. Eius sed eius sit consectetur quaerat. Voluptatem dolorem porro etincidunt labore aliquam quisquam. Adipisci quisquam dolorem dolorem magnam dolorem ipsum. Consectetur quaerat magnam sit voluptatem.', - add_date: '2024-10-02T00:00:00-04:00', - views: 666, - media_type: 'video', - state: 'public', - duration: 13, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/58008fdc69d34c229a85f29076004639.VID_20230917_094453.mp4_Pe8a1dv.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/58008fdc69d34c229a85f29076004639.tmp85b478_u.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 10, - dislikes: 3, - reported_times: 1, - featured: true, - user_featured: false, - size: '35.0MB', - }, - { - friendly_token: 'tsgNaSe6E', - url: 'https://demo.mediacms.io/view?m=tsgNaSe6E', - api_url: 'https://demo.mediacms.io/api/v1/media/tsgNaSe6E', - user: 'markos', - title: 'Magnam ipsum eius numquam quiquia non adipisci.', - description: - 'Adipisci labore dolorem ipsum quaerat non dolore ut. Velit porro neque non consectetur neque neque. Ut sit tempora tempora. Ipsum ut velit neque. Quaerat labore amet porro porro amet tempora. Sed voluptatem est amet quisquam sed numquam velit. Est ipsum non labore. Consectetur amet neque consectetur dolor ipsum.', - add_date: '2024-10-02T05:32:46.253917-04:00', - views: 824, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/0405f61e131f431793644be3742fcc1a.20240628_235522.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 12, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'f9xqzbbJE', - url: 'https://demo.mediacms.io/view?m=f9xqzbbJE', - api_url: 'https://demo.mediacms.io/api/v1/media/f9xqzbbJE', - user: 'markos', - title: 'Magnam quaerat numquam modi dolore sed amet.', - description: - 'Non non voluptatem neque velit labore. Eius labore non aliquam quisquam adipisci neque. Aliquam ipsum sed ipsum quisquam. Sit quaerat sed dolore non tempora. Ipsum sed labore dolore consectetur. Modi non quisquam sed ut ut dolor quaerat.', - add_date: '2024-10-02T05:34:18.498303-04:00', - views: 844, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/369f44b14f944941881a20e8d5285e78.IMG_20240324_151737.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 3, - dislikes: 1, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'DE3KByBeo', - url: 'https://demo.mediacms.io/view?m=DE3KByBeo', - api_url: 'https://demo.mediacms.io/api/v1/media/DE3KByBeo', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 272, - media_type: 'video', - state: 'public', - duration: 29, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/58b35efa3aca454196227c0eb5e2ca75_pkgSAK2.20250517_101207.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/58b35efa3aca454196227c0eb5e2ca75.tmpsw6vmsfo.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 2, - reported_times: 0, - featured: false, - user_featured: false, - size: '62.0MB', - }, - { - friendly_token: 'M8ktwf8kF', - url: 'https://demo.mediacms.io/view?m=M8ktwf8kF', - api_url: 'https://demo.mediacms.io/api/v1/media/M8ktwf8kF', - user: 'markos', - title: 'Quaerat voluptatem quisquam neque velit neque.', - description: - 'Aliquam ipsum quisquam dolor. Modi quisquam neque ut ipsum amet. Tempora quaerat ipsum aliquam velit velit porro est. Consectetur neque eius quisquam porro amet sit neque. Modi voluptatem neque modi. Ipsum aliquam labore quaerat.', - add_date: '2024-10-02T05:34:32.027708-04:00', - views: 852, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/48a682227b544388a1b547736668d0ad.IMG_20240324_151743.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 7, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 's2qAmRTJ9', - url: 'https://demo.mediacms.io/view?m=s2qAmRTJ9', - api_url: 'https://demo.mediacms.io/api/v1/media/s2qAmRTJ9', - user: 'markos', - title: 'Labore neque ipsum labore modi tempora aliquam neque.', - description: - 'Eius voluptatem aliquam sit sit ipsum consectetur. Dolorem velit amet modi. Porro quisquam velit neque dolorem. Dolorem modi quiquia aliquam. Numquam est magnam non numquam modi quisquam est. Sit velit ut labore sit dolore velit modi. Aliquam modi dolorem ut.', - add_date: '2024-10-02T05:34:27.197596-04:00', - views: 779, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/2b786916111947e3ba960d7146ae0424.IMG_20230708_133437.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 2, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: '8pWsxkOS5', - url: 'https://demo.mediacms.io/view?m=8pWsxkOS5', - api_url: 'https://demo.mediacms.io/api/v1/media/8pWsxkOS5', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 321, - media_type: 'video', - state: 'public', - duration: 47, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/d970760faf5745b4b3d0d0cff2b95d86_cvyjd5y.20250517_140535.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/d970760faf5745b4b3d0d0cff2b95d86.tmp3vtt3uip.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 5, - dislikes: 2, - reported_times: 0, - featured: false, - user_featured: false, - size: '101.2MB', - }, - { - friendly_token: 'swcx8A2h1', - url: 'https://demo.mediacms.io/view?m=swcx8A2h1', - api_url: 'https://demo.mediacms.io/api/v1/media/swcx8A2h1', - user: 'markos', - title: 'Etincidunt dolore eius ut non numquam dolore dolorem.', - description: - 'Etincidunt amet dolorem quisquam tempora. Dolorem dolor modi sit modi labore sit. Labore est sed non numquam. Porro non quaerat dolorem porro tempora sit. Ut neque est etincidunt velit eius. Etincidunt aliquam adipisci sed quiquia modi. Adipisci non sed adipisci velit.', - add_date: '2024-10-02T05:38:43-04:00', - views: 7973, - media_type: 'video', - state: 'public', - duration: 31, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/fe4933d67b884d4da507dd60e77f7438.VID_20200909_141053.mp4_bU90dbl.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/fe4933d67b884d4da507dd60e77f7438.tmpdd72kiwh.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 230, - dislikes: 62, - reported_times: 1, - featured: true, - user_featured: false, - size: '65.9MB', - }, - { - friendly_token: 'rNefa4WtV', - url: 'https://demo.mediacms.io/view?m=rNefa4WtV', - api_url: 'https://demo.mediacms.io/api/v1/media/rNefa4WtV', - user: 'markos', - title: 'Quaerat modi non eius.', - description: - 'Quisquam ut dolorem dolorem quisquam dolore. Non modi etincidunt labore sit quisquam. Sed neque quaerat quisquam voluptatem. Numquam labore neque etincidunt. Magnam etincidunt porro adipisci.', - add_date: '2024-10-02T05:36:46.062913-04:00', - views: 2683, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/ca0e3af507c64fc5995b9d97e4a8c779.20240527_091011.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 45, - dislikes: 16, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'LP09dv0mx', - url: 'https://demo.mediacms.io/view?m=LP09dv0mx', - api_url: 'https://demo.mediacms.io/api/v1/media/LP09dv0mx', - user: 'markos', - title: 'Est ipsum non etincidunt voluptatem adipisci labore.', - description: - 'Est sit voluptatem numquam ut etincidunt. Adipisci sed dolor voluptatem labore. Quiquia est sit eius eius labore velit. Tempora ut tempora neque. Ipsum eius sit labore amet dolorem non non. Quiquia velit amet eius sit ut ut voluptatem. Quiquia sit ut ipsum ipsum neque. Amet etincidunt aliquam consectetur voluptatem sed etincidunt quiquia. Sit eius dolore magnam sed velit consectetur. Etincidunt amet numquam sit porro.', - add_date: '2024-10-02T05:31:41.087014-04:00', - views: 711, - media_type: 'video', - state: 'public', - duration: 26, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/980decd203f245bbb3723cba73a94a11.VID_20230813_104846.mp4_3rwZtxQ.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/980decd203f245bbb3723cba73a94a11.tmpmddawiqe.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 11, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: '66.4MB', - }, - { - friendly_token: 'just_somethi', - url: 'https://demo.mediacms.io/view?m=just_somethi', - api_url: 'https://demo.mediacms.io/api/v1/media/just_somethi', - user: 'markos', - title: 'Sit consectetur dolore numquam.', - description: - 'Consectetur adipisci neque neque tempora. Amet quiquia ut labore non sit. Dolor aliquam quiquia adipisci dolor dolorem quiquia. Dolore porro modi labore quisquam adipisci numquam non. Dolor consectetur ut est neque.', - add_date: '2024-10-02T00:00:00-04:00', - views: 1288, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/7aaa65ac24224fe3a768aa6b7a723b58.20240527_090952.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 28, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'PbsYTGEol', - url: 'https://demo.mediacms.io/view?m=PbsYTGEol', - api_url: 'https://demo.mediacms.io/api/v1/media/PbsYTGEol', - user: 'markos', - title: 'Voluptatem porro neque tempora dolorem quiquia est dolor.', - description: - 'Labore aliquam dolorem quiquia est ipsum quiquia. Sed est amet non ipsum. Labore etincidunt etincidunt quiquia amet tempora tempora. Aliquam velit ipsum consectetur. Ipsum labore quaerat quiquia aliquam magnam. Quisquam ut velit velit dolorem dolorem. Aliquam quaerat tempora quisquam ut voluptatem voluptatem quiquia.', - add_date: '2024-10-02T05:33:48.024941-04:00', - views: 785, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/f01faaa2e7be4c9aa7598ab755898a09.IMG_20240324_141304.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 14, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'mkpfy31bY', - url: 'https://demo.mediacms.io/view?m=mkpfy31bY', - api_url: 'https://demo.mediacms.io/api/v1/media/mkpfy31bY', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 212, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/c2d40995ce7640e3b8cbfee1a2890c51.20250517_183010.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 2, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'w2lYWaW8e', - url: 'https://demo.mediacms.io/view?m=w2lYWaW8e', - api_url: 'https://demo.mediacms.io/api/v1/media/w2lYWaW8e', - user: 'markos', - title: 'Plane view approaching Copenhagen airport', - description: 'plane view', - add_date: '2025-06-06T00:00:00-04:00', - views: 664, - media_type: 'video', - state: 'public', - duration: 50, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/e84f1caf58f44d838456625ffe96173b_LQCWsAe.20250603_110810.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/e84f1caf58f44d838456625ffe96173b.tmp7hm26nok.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 13, - dislikes: 3, - reported_times: 0, - featured: false, - user_featured: false, - size: '108.8MB', - }, - { - friendly_token: 'qLMrr970w', - url: 'https://demo.mediacms.io/view?m=qLMrr970w', - api_url: 'https://demo.mediacms.io/api/v1/media/qLMrr970w', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 215, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/558f53227cc5418c9b7d66a3740fe2f8.20250517_082340.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 2, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: 'elygiagorgechania', - url: 'https://demo.mediacms.io/view?m=elygiagorgechania', - api_url: 'https://demo.mediacms.io/api/v1/media/elygiagorgechania', - user: 'markos', - title: 'Exit of Elygia Gorge, Chania, Crete', - description: - 'This video is from the exit of Elygia Gorge, Chania, Crete, where it meets the sea!', - add_date: '2025-06-15T00:00:00-04:00', - views: 688, - media_type: 'video', - state: 'public', - duration: 29, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/c1ab03cab3bb46b5854a5e217cfe3013_Nete6ao.VID_20230813_144422.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/c1ab03cab3bb46b5854a5e217cfe3013.tmpjlxkhy0i.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 0, - reported_times: 0, - featured: false, - user_featured: false, - size: '75.6MB', - }, - { - friendly_token: 'OxO6BMVZb', - url: 'https://demo.mediacms.io/view?m=OxO6BMVZb', - api_url: 'https://demo.mediacms.io/api/v1/media/OxO6BMVZb', - user: 'markos', - title: 'Eius velit etincidunt amet tempora ut.', - description: - 'Aliquam eius adipisci adipisci. Quaerat dolor quaerat magnam. Amet ut quaerat sit sed magnam quaerat neque. Neque velit porro labore modi ut ut ut. Non quaerat consectetur dolor eius voluptatem. Quisquam modi amet sed magnam eius. Quisquam dolor dolore aliquam quisquam neque dolore. Quisquam dolor ut ipsum quiquia. Voluptatem quisquam neque quisquam quiquia adipisci. Est modi eius est etincidunt numquam quisquam ut.', - add_date: '2024-10-02T05:34:33.461809-04:00', - views: 1023, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/13299e6838e143fda776bacf7081484e.IMG_20230820_200357.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 4, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'hDHXkdwy0', - url: 'https://demo.mediacms.io/view?m=hDHXkdwy0', - api_url: 'https://demo.mediacms.io/api/v1/media/hDHXkdwy0', - user: 'markos', - title: 'Modi tempora est quaerat numquam', - description: - 'Magnam voluptatem est magnam dolorem. Etincidunt quiquia aliquam velit tempora porro. Magnam neque eius eius etincidunt ut ipsum. Adipisci labore quaerat modi. Ipsum modi quaerat consectetur est non quaerat sed. Neque ut modi adipisci dolore adipisci dolor ut. Dolor tempora adipisci quisquam. Dolorem consectetur velit adipisci etincidunt voluptatem. Non quisquam voluptatem adipisci. Voluptatem est aliquam porro labore non.', - add_date: '2024-10-02T05:36:42-04:00', - views: 1679, - media_type: 'video', - state: 'public', - duration: 24, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/a3c5642e13624149897f193981ebccf3.VID_20210307_111552.mp4_uEHcD0C.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/a3c5642e13624149897f193981ebccf3.tmpempjz6eh.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 32, - dislikes: 12, - reported_times: 0, - featured: true, - user_featured: false, - size: '52.4MB', - }, - { - friendly_token: 'vDKrrkIVc', - url: 'https://demo.mediacms.io/view?m=vDKrrkIVc', - api_url: 'https://demo.mediacms.io/api/v1/media/vDKrrkIVc', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 228, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/50f296fd588240d2ad80a6fb9a5ce7d6.20250518_093811.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 6, - dislikes: 1, - reported_times: 0, - featured: false, - user_featured: false, - size: null, - }, - { - friendly_token: '4h3nsvXb1', - url: 'https://demo.mediacms.io/view?m=4h3nsvXb1', - api_url: 'https://demo.mediacms.io/api/v1/media/4h3nsvXb1', - user: 'markos', - title: 'Dolor voluptatem non quiquia consectetur est numquam sed.', - description: - 'Aliquam ipsum etincidunt neque ipsum. Consectetur ut non velit quaerat porro. Eius ut voluptatem velit aliquam dolor. Non etincidunt est quaerat quaerat. Quiquia est non ipsum numquam. Quisquam amet magnam sed eius quaerat. Magnam porro dolorem dolor. Numquam numquam quaerat est. Quisquam tempora ut quaerat est.', - add_date: '2024-10-02T05:32:43.865153-04:00', - views: 981, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/baca04d3009d4daba302919c25b4325e.IMG_1936.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 16, - dislikes: 1, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'HdUU8boQP', - url: 'https://demo.mediacms.io/view?m=HdUU8boQP', - api_url: 'https://demo.mediacms.io/api/v1/media/HdUU8boQP', - user: 'markos', - title: 'Consectetur adipisci porro quiquia ipsum aliquam etincidunt ut.', - description: - 'Consectetur numquam eius amet est dolor neque modi. Consectetur est amet voluptatem quaerat numquam sed. Porro tempora ut ut. Non dolor amet sit. Labore porro neque dolorem numquam dolore ut. Modi sed adipisci dolore. Numquam magnam est tempora. Neque aliquam labore dolor ipsum porro.', - add_date: '2024-10-02T05:34:13.171233-04:00', - views: 795, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/e1df55b16b3b456ea88bf7feb7db6051.IMG_20230708_120717.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 8, - dislikes: 3, - reported_times: 0, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'vy5PTWJZ6', - url: 'https://demo.mediacms.io/view?m=vy5PTWJZ6', - api_url: 'https://demo.mediacms.io/api/v1/media/vy5PTWJZ6', - user: 'markos', - title: 'Non etincidunt numquam velit.', - description: - 'Etincidunt ut velit ipsum. Labore modi magnam eius quisquam. Dolorem magnam sit quiquia non dolorem tempora. Aliquam labore sed quaerat magnam est aliquam porro. Adipisci adipisci aliquam tempora ut aliquam eius amet. Est etincidunt quiquia dolorem amet consectetur. Ipsum neque dolorem dolore etincidunt.\r\n', - add_date: '2024-10-02T05:33:26-04:00', - views: 713, - media_type: 'image', - state: 'public', - duration: 0, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/7a9ec6be9ce24a569a246c61d9b03690.IMG_20220528_135153.jpg.jpg', - is_reviewed: true, - preview_url: null, - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 9, - dislikes: 1, - reported_times: 1, - featured: true, - user_featured: false, - size: null, - }, - { - friendly_token: 'TAdmfDUlu', - url: 'https://demo.mediacms.io/view?m=TAdmfDUlu', - api_url: 'https://demo.mediacms.io/api/v1/media/TAdmfDUlu', - user: 'markos', - title: 'Sed neque adipisci dolorem sed.', - description: - 'Quiquia ipsum velit amet. Consectetur porro numquam numquam magnam adipisci dolore. Dolor ipsum ut ut consectetur modi labore. Neque est non amet. Sit quiquia quisquam dolorem. Modi dolore modi dolorem ipsum ipsum. Neque modi modi dolorem quisquam numquam modi quaerat.\r\n\r\nbest scenes at 00:00:12 and 00:14', - add_date: '2024-10-02T00:00:00-04:00', - views: 821, - media_type: 'video', - state: 'public', - duration: 30, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/f371a6b2c157451d924bc4f612bf2667_Kh4GigX.Pexels_Videos_2079217_1.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/f371a6b2c157451d924bc4f612bf2667.tmp2jqxf9sr.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 20, - dislikes: 4, - reported_times: 0, - featured: true, - user_featured: false, - size: '90.0MB', - }, - { - friendly_token: 'kHd7EKAVH', - url: 'https://demo.mediacms.io/view?m=kHd7EKAVH', - api_url: 'https://demo.mediacms.io/api/v1/media/kHd7EKAVH', - user: 'markos', - title: 'Tempora magnam velit ipsum neque aliquam adipisci.', - description: - 'Porro dolorem eius sed non eius. Non dolor quiquia dolorem. Modi ut dolor aliquam dolor. Non est dolorem amet consectetur neque quiquia numquam. Aliquam adipisci quiquia voluptatem ipsum quisquam magnam adipisci. Sit adipisci dolor consectetur dolor quaerat. Magnam ut modi tempora. Modi non ipsum tempora etincidunt porro. Ut ut dolor ipsum non consectetur neque quiquia.', - add_date: '2024-10-02T05:33:57.651288-04:00', - views: 1051, - media_type: 'video', - state: 'public', - duration: 54, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/9d3b8425eb08400fa08d90f988bc5ff4.VID_20220821_110509.mp4_JzAol5C.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/9d3b8425eb08400fa08d90f988bc5ff4.tmpwlnjum5k.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 26, - dislikes: 8, - reported_times: 1, - featured: true, - user_featured: false, - size: '136.8MB', - }, - { - friendly_token: 'Otbc37Yj4', - url: 'https://demo.mediacms.io/view?m=Otbc37Yj4', - api_url: 'https://demo.mediacms.io/api/v1/media/Otbc37Yj4', - user: 'markos', - title: 'Kastania Evrytanias, Central Greece', - description: '', - add_date: '2025-05-19T00:00:00-04:00', - views: 311, - media_type: 'video', - state: 'public', - duration: 25, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/dd3af0e1dece43b490bbafc9400a407a_YtfxVr4.20250517_105515.mp4.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/dd3af0e1dece43b490bbafc9400a407a.tmpl3iqzl10.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 12, - dislikes: 1, - reported_times: 0, - featured: false, - user_featured: false, - size: '54.3MB', - }, - { - friendly_token: 'a1BP6J0fM', - url: 'https://demo.mediacms.io/view?m=a1BP6J0fM', - api_url: 'https://demo.mediacms.io/api/v1/media/a1BP6J0fM', - user: 'markos', - title: 'Velit sed magnam quiquia amet.', - description: - 'Numquam quiquia numquam ut etincidunt numquam. Dolore ut sit eius dolorem sed. Neque porro modi dolor ipsum amet dolore quisquam. Ipsum dolore dolor voluptatem eius quiquia etincidunt. Dolore etincidunt amet velit amet ipsum ut. Aliquam etincidunt consectetur est. Consectetur non quiquia voluptatem velit sed quisquam.', - add_date: '2024-10-02T05:35:15.434023-04:00', - views: 997, - media_type: 'video', - state: 'public', - duration: 11, - thumbnail_url: - 'https://demo.mediacms.io/media/original/thumbnails/user/markos/32e2cf3ff5fe498da93251034e977d9c.20240527_090548.mp4_qiF5S9H.jpg', - is_reviewed: true, - preview_url: - 'https://demo.mediacms.io/media/encoded/1/markos/32e2cf3ff5fe498da93251034e977d9c.tmpheuxmj3y.gif', - author_name: 'Markos Gogoulos', - author_profile: 'https://demo.mediacms.io/user/markos/', - author_thumbnail: 'https://demo.mediacms.io/media/userlogos/2024/10/02/markos.jpeg', - encoding_status: 'success', - likes: 14, - dislikes: 1, - reported_times: 0, - featured: true, - user_featured: false, - size: '3.5MB', - }, - ], - - // VIDEO - media_type: 'video', - original_media_url: '/media/original/user/markos/d6ae9093cb1648529432f38ee1198200.video.mp4', - hls_info: { - master_file: '/media/hls/d6ae9093cb1648529432f38ee1198200/master.m3u8', - '144_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-1/iframes.m3u8', - '240_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-2/iframes.m3u8', - '360_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-3/iframes.m3u8', - '480_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-4/iframes.m3u8', - '720_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-5/iframes.m3u8', - '1080_iframe': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-6/iframes.m3u8', - '144_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-1/stream.m3u8', - '240_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-2/stream.m3u8', - '360_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-3/stream.m3u8', - '480_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-4/stream.m3u8', - '720_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-5/stream.m3u8', - '1080_playlist': '/media/hls/d6ae9093cb1648529432f38ee1198200/media-6/stream.m3u8', - }, - encodings_info: { - 144: { - h264: { - title: 'h264-144', - url: '/media/encoded/23/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '0.3MB', - encoding_id: 1, - status: 'success', - }, - }, - 240: { - h264: { - title: 'h264-240', - url: '/media/encoded/2/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '0.6MB', - encoding_id: 2, - status: 'success', - }, - }, - 360: { - h264: { - title: 'h264-360', - url: '/media/encoded/3/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '0.8MB', - encoding_id: 3, - status: 'success', - }, - }, - 480: { - h264: { - title: 'h264-480', - url: '/media/encoded/13/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '1.5MB', - encoding_id: 4, - status: 'success', - }, - }, - 720: { - h264: { - title: 'h264-720', - url: '/media/encoded/10/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '3.5MB', - encoding_id: 5, - status: 'success', - }, - }, - 1080: { - h264: { - title: 'h264-1080', - url: '/media/encoded/7/markos/d6ae9093cb1648529432f38ee1198200.d6ae9093cb1648529432f38ee1198200.video.mp4.mp4', - progress: 100, - size: '6.4MB', - encoding_id: 6, - status: 'success', - }, - }, - 1440: {}, - 2160: {}, - }, - - // AUDIO - /*media_type: 'audio', - original_media_url: - 'https://videojs.mediacms.io/media/original/user/markos/174be7a1ecb04850a6927a0af2887ccc.SizzlaHardGround.mp3', - hls_info: {}, - encodings_info: {},*/ - }, - - // other - useRoundedCorners: false, - isPlayList: false, - previewSprite: { - url: 'https://videojs.mediacms.io/media/original/thumbnails/user/markos/d6ae9093cb1648529432f38ee1198200.video.mp4sprites.jpg', - frame: { width: 160, height: 90, seconds: 10 }, - }, - siteUrl: 'https://videojs.mediacms.io', - nextLink: 'https://videojs.mediacms.io/view?m=YjGJafibO', - urlAutoplay: true, - urlMuted: false, - }, - [] - ); - - // Define chapters as JSON object - // Note: The sample-chapters.vtt file is no longer needed as chapters are now loaded from this JSON - // CONDITIONAL LOGIC: - // - When chaptersData has content: Uses original ChapterMarkers with sprite preview - // - When chaptersData is empty: Uses separate SpritePreview component - // Utility function to convert time string (HH:MM:SS.mmm) to seconds - const convertTimeStringToSeconds = (timeString) => { - if (typeof timeString === 'number') { - return timeString; // Already in seconds - } - - if (typeof timeString !== 'string') { - return 0; - } - - const parts = timeString.split(':'); - if (parts.length !== 3) { - return 0; - } - - const hours = parseInt(parts[0], 10) || 0; - const minutes = parseInt(parts[1], 10) || 0; - const seconds = parseFloat(parts[2]) || 0; - - return hours * 3600 + minutes * 60 + seconds; - }; - - // Convert chapters data from backend format to required format with memoization - const convertChaptersData = useMemo(() => { - return (rawChaptersData) => { - if (!rawChaptersData || !Array.isArray(rawChaptersData)) { - return []; - } - - const convertedData = rawChaptersData.map((chapter) => ({ - startTime: convertTimeStringToSeconds(chapter.startTime), - endTime: convertTimeStringToSeconds(chapter.endTime), - chapterTitle: chapter.chapterTitle, - })); - - return convertedData; - }; - }, []); - - // Helper function to check if chapters represent a meaningful chapter structure - // Returns false if there's only one chapter covering the entire video duration with a generic title - const hasRealChapters = useMemo(() => { - return (rawChaptersData, videoDuration) => { - if (!rawChaptersData || !Array.isArray(rawChaptersData) || rawChaptersData.length === 0) { - return false; - } - - // If there's more than one chapter, assume it's a real chapter structure - if (rawChaptersData.length > 1) { - return true; - } - - // If there's only one chapter, check if it's a generic segment marker - if (rawChaptersData.length === 1) { - const chapter = rawChaptersData[0]; - const startTime = convertTimeStringToSeconds(chapter.startTime); - const endTime = convertTimeStringToSeconds(chapter.endTime); - - // Check if it's a generic segment with common auto-generated titles - const isGenericTitle = chapter.chapterTitle - ?.toLowerCase() - .match(/^(segment|video|full video|chapter|part)$/); - - // If we have video duration info, check if this single chapter spans the whole video - if (videoDuration && videoDuration > 0) { - // Allow for small timing differences (1 second tolerance) - const tolerance = 1; - const isFullVideo = startTime <= tolerance && Math.abs(endTime - videoDuration) <= tolerance; - - // Only hide if it's both full video AND has a generic title - if (isFullVideo && isGenericTitle) { - return false; - } - - // If it doesn't span the full video, it's a real chapter - if (!isFullVideo) { - return true; - } - } - - // Fallback: If start time is 0 and the title is generic, assume it's not a real chapter - if (startTime === 0 && isGenericTitle) { - return false; - } - } - - return true; - }; - }, []); - - // Memoized chapters data conversion - const chaptersData = useMemo(() => { - if (mediaData?.data?.chapter_data && mediaData?.data?.chapter_data.length > 0) { - const videoDuration = mediaData?.data?.duration || null; - - // Check if we have real chapters or just a single segment - if (hasRealChapters(mediaData.data.chapter_data, videoDuration)) { - return convertChaptersData(mediaData?.data?.chapter_data); - } else { - // Return empty array if it's just a single segment covering the whole video - return []; - } - } - return isDevMode - ? [ - { startTime: '00:00:00.000', endTime: '00:00:04.000', chapterTitle: 'Introduction' }, - { startTime: '00:00:05.000', endTime: '00:00:10.000', chapterTitle: 'Overview of Marine Life' }, - { startTime: '00:00:10.000', endTime: '00:00:15.000', chapterTitle: 'Coral Reef Ecosystems' }, - { startTime: '00:00:15.000', endTime: '00:00:20.000', chapterTitle: 'Deep Sea Creatures' }, - { startTime: '00:00:20.000', endTime: '00:00:30.000', chapterTitle: 'Ocean Conservation' }, - { startTime: '00:00:24.000', endTime: '00:00:32.000', chapterTitle: 'Ocean Conservation' }, - { startTime: '00:00:32.000', endTime: '00:00:40.000', chapterTitle: 'Climate Change Impact' }, - { startTime: '00:00:40.000', endTime: '00:00:48.000', chapterTitle: 'Marine Protected Areas' }, - { startTime: '00:00:48.000', endTime: '00:00:56.000', chapterTitle: 'Sustainable Fishing' }, - { startTime: '00:00:56.000', endTime: '00:00:64.000', chapterTitle: 'Research Methods' }, - { startTime: '00:00:64.000', endTime: '00:00:72.000', chapterTitle: 'Future Challenges' }, - { startTime: '00:00:72.000', endTime: '00:00:80.000', chapterTitle: 'Conclusion' }, - { startTime: '00:00:80.000', endTime: '00:00:88.000', chapterTitle: 'Marine Biodiversity Hotspots' }, - { startTime: '00:00:88.000', endTime: '00:00:96.000', chapterTitle: 'Marine Biodiversity test' }, - { startTime: '00:00:96.000', endTime: '00:01:04.000', chapterTitle: 'Whale Migration Patterns' }, - { startTime: '00:01:04.000', endTime: '00:01:12.000', chapterTitle: 'Plastic Pollution Crisis' }, - { startTime: '00:01:12.000', endTime: '00:01:20.000', chapterTitle: 'Seagrass Meadows' }, - { startTime: '00:01:20.000', endTime: '00:01:28.000', chapterTitle: 'Ocean Acidification' }, - { startTime: '00:01:28.000', endTime: '00:01:36.000', chapterTitle: 'Marine Archaeology' }, - { startTime: '00:01:28.000', endTime: '00:01:36.000', chapterTitle: 'Tidal Pool Ecosystems' }, - { startTime: '00:01:36.000', endTime: '00:01:44.000', chapterTitle: 'Commercial Aquaculture' }, - { startTime: '00:01:44.000', endTime: '00:01:52.000', chapterTitle: 'Ocean Exploration Technology' }, - ].map((chapter) => ({ - startTime: convertTimeStringToSeconds(chapter.startTime), - endTime: convertTimeStringToSeconds(chapter.endTime), - chapterTitle: chapter.chapterTitle, - })) - : []; - }, [mediaData?.data?.chapter_data, mediaData?.data?.duration, isDevMode, convertChaptersData, hasRealChapters]); - - // Helper function to determine MIME type based on file extension or media type - const getMimeType = (url, mediaType) => { - if (mediaType === 'audio') { - if (url && url.toLowerCase().includes('.mp3')) { - return 'audio/mpeg'; - } - if (url && url.toLowerCase().includes('.ogg')) { - return 'audio/ogg'; - } - if (url && url.toLowerCase().includes('.wav')) { - return 'audio/wav'; - } - if (url && url.toLowerCase().includes('.m4a')) { - return 'audio/mp4'; - } - // Default audio MIME type - return 'audio/mpeg'; - } - - // Default to video/mp4 for video content - if (url && url.toLowerCase().includes('.webm')) { - return 'video/webm'; - } - if (url && url.toLowerCase().includes('.ogg')) { - return 'video/ogg'; - } - - // Default video MIME type - return 'video/mp4'; - }; - - // Get user's quality preference for dependency tracking - const userQualityPreference = userPreferences.current.getQualityPreference(); - - // Get video data from mediaData - const currentVideo = useMemo(() => { - // Get video sources based on available data and user preferences - const getVideoSources = () => { - // Use the extracted quality preference - const userQuality = userQualityPreference; - - // Check if HLS info is available and not empty - if (mediaData.data?.hls_info) { - // If user prefers auto quality or master file doesn't exist for specific quality - if (userQuality === 'auto' && mediaData.data.hls_info.master_file) { - return [ - { - src: mediaData.siteUrl + mediaData.data.hls_info.master_file, - type: 'application/x-mpegURL', // HLS MIME type - label: 'Auto', - }, - ]; - } - - // If user has selected a specific quality, try to use that playlist - if (userQuality !== 'auto') { - const qualityKey = `${userQuality.replace('p', '')}_playlist`; - if (mediaData.data.hls_info[qualityKey]) { - return [ - { - src: mediaData.siteUrl + mediaData.data.hls_info[qualityKey], - type: 'application/x-mpegURL', // HLS MIME type - label: `${userQuality}p`, - }, - ]; - } - } - - // Fallback to master file if specific quality not available - if (mediaData.data.hls_info.master_file) { - return [ - { - src: mediaData.siteUrl + mediaData.data.hls_info.master_file, - type: 'application/x-mpegURL', // HLS MIME type - label: 'Auto', - }, - ]; - } - } - - // Fallback to encoded qualities if available - if (mediaData.data?.encodings_info) { - const encodings = mediaData.data.encodings_info; - const userQuality = userQualityPreference; - - // If user has selected a specific quality, try to use that encoding first - if (userQuality !== 'auto') { - const qualityNumber = userQuality.replace('p', ''); // Remove 'p' from '240p' -> '240' - if ( - encodings[qualityNumber] && - encodings[qualityNumber].h264 && - encodings[qualityNumber].h264.url - ) { - return [ - { - src: encodings[qualityNumber].h264.url, - type: getMimeType(encodings[qualityNumber].h264.url, mediaData.data?.media_type), - label: `${qualityNumber}p`, - }, - ]; - } - } - - // If auto quality or specific quality not available, return all available qualities - const sources = []; - - // Get available qualities dynamically from encodings_info - const availableQualities = Object.keys(encodings) - .filter((quality) => encodings[quality] && encodings[quality].h264 && encodings[quality].h264.url) - .sort((a, b) => parseInt(b) - parseInt(a)); // Sort descending (highest first) - - for (const quality of availableQualities) { - const sourceUrl = encodings[quality].h264.url; - sources.push({ - src: sourceUrl, - type: getMimeType(sourceUrl, mediaData.data?.media_type), - label: `${quality}p`, - }); - } - - if (sources.length > 0) { - return sources; - } - } - - // Final fallback to original media URL or sample video - if (mediaData.data?.original_media_url) { - const sourceUrl = mediaData.siteUrl + mediaData.data.original_media_url; - return [ - { - src: sourceUrl, - type: getMimeType(sourceUrl, mediaData.data?.media_type), - }, - ]; - } - - // Default sample video - return [ - { - src: '/videos/sample-video-white.mp4', - type: 'video/mp4', - }, - /* { - src: '/videos/sample-video.mp3', - type: 'audio/mpeg', - }, */ - ]; - }; - - const currentVideo = { - id: mediaData.data?.friendly_token || 'default-video', - title: mediaData.data?.title || 'Video', - author_name: mediaData.data?.author_name || 'Unknown', - author_profile: mediaData.data?.author_profile ? mediaData.siteUrl + mediaData.data.author_profile : '', - author_thumbnail: mediaData.data?.author_thumbnail - ? mediaData.siteUrl + mediaData.data.author_thumbnail - : '', - url: mediaData.data?.url || '', - poster: mediaData.data?.poster_url ? mediaData.siteUrl + mediaData.data.poster_url : '', - previewSprite: mediaData?.previewSprite || {}, - useRoundedCorners: mediaData?.useRoundedCorners, - isPlayList: mediaData?.isPlayList, - related_media: mediaData.data?.related_media || [], - nextLink: mediaData?.nextLink || null, - urlAutoplay: mediaData?.urlAutoplay || true, - urlMuted: mediaData?.urlMuted || false, - sources: getVideoSources(), - }; - - return currentVideo; - }, [mediaData, userQualityPreference]); - - // Compute available qualities. Prefer JSON (mediaData.data.qualities), otherwise build from encodings_info or current source. - const availableQualities = useMemo(() => { - // Generate desiredOrder dynamically based on available data - const generateDesiredOrder = () => { - const baseOrder = ['auto']; - - // Add qualities from encodings_info if available - if (mediaData.data?.encodings_info) { - const availableQualities = Object.keys(mediaData.data.encodings_info) - .filter((quality) => { - const encoding = mediaData.data.encodings_info[quality]; - return encoding && encoding.h264 && encoding.h264.url; - }) - .map((quality) => `${quality}p`) - .sort((a, b) => parseInt(a) - parseInt(b)); // Sort ascending - - baseOrder.push(...availableQualities); - } else { - // Fallback to standard order - baseOrder.push('144p', '240p', '360p', '480p', '720p', '1080p', '1440p', '2160p'); - } - - return baseOrder; - }; - - const desiredOrder = generateDesiredOrder(); - - const normalize = (arr) => { - const norm = arr.map((q) => ({ - label: q.label || q.value || 'Auto', - value: (q.value || q.label || 'auto').toString().toLowerCase(), - src: q.src || q.url || q.href, - type: q.type || getMimeType(q.src || q.url || q.href, mediaData.data?.media_type), - })); - - // Only include qualities that have actual sources - const validQualities = norm.filter((q) => q.src); - - // sort based on desired order - const idx = (v) => { - const i = desiredOrder.indexOf(String(v).toLowerCase()); - return i === -1 ? 999 : i; - }; - validQualities.sort((a, b) => idx(a.value) - idx(b.value)); - return validQualities; - }; - - const jsonList = mediaData?.data?.qualities; - if (Array.isArray(jsonList) && jsonList.length) { - return normalize(jsonList); - } - - // If HLS is available, build qualities from HLS playlists - if (mediaData.data?.hls_info && mediaData.data.hls_info.master_file) { - const hlsInfo = mediaData.data.hls_info; - const qualities = []; - - // Add master file as auto quality - qualities.push({ - label: 'Auto', - value: 'auto', - src: mediaData.siteUrl + hlsInfo.master_file, - type: 'application/x-mpegURL', - }); - - // Add individual HLS playlists - Object.keys(hlsInfo).forEach((key) => { - if (key.endsWith('_playlist')) { - const quality = key.replace('_playlist', ''); - qualities.push({ - label: `${quality}p`, - value: `${quality}p`, - src: mediaData.siteUrl + hlsInfo[key], - type: 'application/x-mpegURL', - }); - } - }); - - return normalize(qualities); - } - - // Build from encodings_info if available - if (mediaData.data?.encodings_info) { - const encodings = mediaData.data.encodings_info; - const qualities = []; - - // Add auto quality first - qualities.push({ - label: 'Auto', - value: 'auto', - src: null, // Will use the highest available quality - type: getMimeType(null, mediaData.data?.media_type), - }); - - // Add available encoded qualities dynamically - Object.keys(encodings).forEach((quality) => { - if (encodings[quality] && encodings[quality].h264 && encodings[quality].h264.url) { - const sourceUrl = encodings[quality].h264.url; - qualities.push({ - label: `${quality}p`, - value: `${quality}p`, - src: sourceUrl, - type: getMimeType(sourceUrl, mediaData.data?.media_type), - }); - } - }); - - if (qualities.length > 1) { - // More than just auto - return normalize(qualities); - } - } - - // Build from current source as fallback - only if we have a valid source - const baseSrc = (currentVideo?.sources && currentVideo.sources[0]?.src) || null; - const type = - (currentVideo?.sources && currentVideo.sources[0]?.type) || - getMimeType(baseSrc, mediaData.data?.media_type); - - if (baseSrc) { - const buildFromBase = [ - { - label: 'Auto', - value: 'auto', - src: baseSrc, - type, - }, - ]; - return normalize(buildFromBase); - } - - // Return empty array if no valid sources found - return []; - }, [mediaData, currentVideo]); - - // Get related videos from mediaData instead of static data - const relatedVideos = useMemo(() => { - if (!mediaData?.data?.related_media) { - return []; - } - - return mediaData.data.related_media - .slice(0, 12) // Limit to maximum 12 items - .map((media) => ({ - id: media.friendly_token, - title: media.title, - author: media.user || media.author_name || 'Unknown', - views: `${media.views} views`, - thumbnail: media.thumbnail_url || media.author_thumbnail, - category: media.media_type, - url: media.url, - duration: media.duration, - size: media.size, - likes: media.likes, - dislikes: media.dislikes, - add_date: media.add_date, - description: media.description, - })); - }, [mediaData]); - - // Demo array for testing purposes - const demoSubtitleTracks = [ - { - kind: 'subtitles', - src: '/sample-subtitles.vtt', - srclang: 'en', - label: 'English Subtitles', - default: false, - }, - { - kind: 'subtitles', - src: '/sample-subtitles-greek.vtt', - srclang: 'el', - label: 'Greek Subtitles (Ελληνικά)', - default: false, - }, - ]; - // const demoSubtitleTracks = []; // NO Subtitles. TODO: hide it on production - - // Get subtitle tracks from backend response or fallback based on environment - const backendSubtitles = mediaData?.data?.subtitles_info || (isDevMode ? demoSubtitleTracks : []); - const hasSubtitles = backendSubtitles.length > 0; - const subtitleTracks = hasSubtitles - ? backendSubtitles.map((track) => ({ - kind: 'subtitles', - src: track.src, - srclang: track.srclang, - label: track.label, - default: false, - })) - : []; - - // Function to navigate to next video - const goToNextVideo = () => { - if (mediaData.onClickNextCallback && typeof mediaData.onClickNextCallback === 'function') { - mediaData.onClickNextCallback(); - } - }; - - useEffect(() => { - // Only initialize if we don't already have a player and element exists - if (videoRef.current && !playerRef.current) { - // Check if element is already a Video.js player - if (videoRef.current.player) { - return; - } - - const timer = setTimeout(() => { - // Double-check that we still don't have a player and element exists - if (!playerRef.current && videoRef.current && !videoRef.current.player) { - playerRef.current = videojs(videoRef.current, { - // ===== STANDARD