{"id":56,"date":"2025-08-27T15:05:33","date_gmt":"2025-08-27T15:05:33","guid":{"rendered":"https:\/\/scootercam.net\/notes\/?p=56"},"modified":"2025-08-27T15:05:33","modified_gmt":"2025-08-27T15:05:33","slug":"revised-timelapse-method","status":"publish","type":"post","link":"https:\/\/scootercam.net\/blog\/revised-timelapse-method\/","title":{"rendered":"Revised timelapse method"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Daily Video Output: 8 Videos Breakdown<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Video Structure (Per Day)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Amcrest Camera (4 videos)<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>amcrest_day_20250827.mp4<\/code> &#8211; 8:00am to 4:00pm<\/li>\n\n\n\n<li><code>amcrest_evening_20250827.mp4<\/code> &#8211; 4:00pm to 12:00am<\/li>\n\n\n\n<li><code>amcrest_night_20250827.mp4<\/code> &#8211; 12:00am to 8:00am<\/li>\n\n\n\n<li><code>amcrest_sunset_20250827.mp4<\/code> &#8211; <strong>30min before sunset \u2192 30min after sunset<\/strong><\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Reolink Camera (4 videos)<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>reolink_day_20250827.mp4<\/code> &#8211; 8:00am to 4:00pm<\/li>\n\n\n\n<li><code>reolink_evening_20250827.mp4<\/code> &#8211; 4:00pm to 12:00am<\/li>\n\n\n\n<li><code>reolink_night_20250827.mp4<\/code> &#8211; 12:00am to 8:00am<\/li>\n\n\n\n<li><code>reolink_sunset_20250827.mp4<\/code> &#8211; <strong>30min before sunset \u2192 30min after sunset<\/strong><\/li>\n<\/ol>\n\n\n\n<p><strong>Total: 8 videos per day<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sunset Video Special Characteristics<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Timing (Using Douglas, MI coordinates)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Already in your script:\nprivate $latitude = 42.5596;\nprivate $longitude = -86.2355;\n\nprivate function getGoldenHourWindow($timestamp = null) {\n    $sun_info = date_sun_info($timestamp, $this-&gt;latitude, $this-&gt;longitude);\n    $sunset_timestamp = $sun_info&#91;'sunset'];\n    \n    return &#91;\n        'start' =&gt; $sunset_timestamp - (30 * 60),  \/\/ 30min before\n        'end' =&gt; $sunset_timestamp + (30 * 60),    \/\/ 30min after\n        'sunset' =&gt; $sunset_timestamp\n    ];\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Cross-Period Collection<\/h3>\n\n\n\n<p>Sunset videos <strong>span period boundaries<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Example August 27, 2025:\nSunset: 7:45 PM\nGolden Hour: 7:15 PM \u2192 8:15 PM\n\nSegments collected from:\n\u251c\u2500\u2500 7:15-8:00 PM (end of \"evening\" period)  \n\u2514\u2500\u2500 8:00-8:15 PM (start of \"night\" period)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Current Script Advantage<\/h3>\n\n\n\n<p>Your script <strong>already identifies golden hour segments<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tags them with <code>_gh<\/code> suffix<\/li>\n\n\n\n<li>Stores them in the same period directories<\/li>\n\n\n\n<li>Calculates the exact golden hour window<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Append Strategy for Sunset Videos<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Challenge: Time-Based vs Period-Based<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Period videos<\/strong>: Append every 15 minutes predictably<\/li>\n\n\n\n<li><strong>Sunset videos<\/strong>: Only append during golden hour window (~1 hour per day)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Implementation Approach<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>public function receiveSegment() {\n    $is_golden_hour = $this-&gt;isSegmentGoldenHour($timestamp);\n    \n    \/\/ Always append to period video\n    $this-&gt;appendToPeriodVideo($camera, $period, $segment);\n    \n    \/\/ Also append to sunset video if golden hour\n    if ($is_golden_hour) {\n        $this-&gt;appendToSunsetVideo($camera, $segment);\n    }\n}\n\nprivate function appendToSunsetVideo($camera, $segment) {\n    $today = date('Ymd');\n    $sunset_video = \"\/final_videos\/{$camera}_sunset_{$today}.mp4\";\n    $temp_video = \"\/temp_build\/{$camera}_sunset_{$today}_building.mp4\";\n    \n    if (!file_exists($sunset_video)) {\n        \/\/ First golden hour segment of the day\n        copy($segment, $sunset_video);\n    } else {\n        \/\/ Append to existing sunset video\n        $this-&gt;fastAppend($sunset_video, $segment, $temp_video);\n        rename($temp_video, $sunset_video);\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">File Naming Convention<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>\/final_videos\/\n\u251c\u2500\u2500 amcrest_day_20250827.mp4      \u2190 8am-4pm, ~480 min\n\u251c\u2500\u2500 amcrest_evening_20250827.mp4  \u2190 4pm-12am, ~480 min  \n\u251c\u2500\u2500 amcrest_night_20250827.mp4    \u2190 12am-8am, ~480 min\n\u251c\u2500\u2500 amcrest_sunset_20250827.mp4   \u2190 Sunset\u00b130min, ~60 min\n\u251c\u2500\u2500 reolink_day_20250827.mp4      \u2190 8am-4pm, ~480 min\n\u251c\u2500\u2500 reolink_evening_20250827.mp4  \u2190 4pm-12am, ~480 min\n\u251c\u2500\u2500 reolink_night_20250827.mp4    \u2190 12am-8am, ~480 min\n\u2514\u2500\u2500 reolink_sunset_20250827.mp4   \u2190 Sunset\u00b130min, ~60 min\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Sunset Video Timing Examples<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Date<\/th><th>Sunset Time<\/th><th>Golden Hour Window<\/th><th>Expected Duration<\/th><\/tr><\/thead><tbody><tr><td>June 21<\/td><td>8:15 PM<\/td><td>7:45 PM &#8211; 8:45 PM<\/td><td>~60 minutes<\/td><\/tr><tr><td>August 27<\/td><td>7:45 PM<\/td><td>7:15 PM &#8211; 8:15 PM<\/td><td>~60 minutes<\/td><\/tr><tr><td>December 21<\/td><td>5:30 PM<\/td><td>5:00 PM &#8211; 6:00 PM<\/td><td>~60 minutes<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><em>Duration = ~60 min = 4 segments (15-min intervals)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Processing Efficiency Gains<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Current Script Waste<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Builds 3 video types per period (regular\/complete\/golden_only)<\/li>\n\n\n\n<li>Re-concatenates everything every 20 minutes<\/li>\n\n\n\n<li><strong>~432 rebuilds per day<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Your Append Approach<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>4 videos per camera, append-only<\/li>\n\n\n\n<li>Constant 2-3 second processing per segment<\/li>\n\n\n\n<li><strong>~96 appends per day<\/strong> (24 hrs \u00d7 4 segments\/hr \u00d7 2 cameras)<\/li>\n<\/ul>\n\n\n\n<p><strong>Result<\/strong>: 98% reduction in processing overhead<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Daily Video Output: 8 Videos Breakdown Video Structure (Per Day) Amcrest Camera (4 videos) Reolink Camera (4 videos) Total: 8 videos per day Sunset Video Special Characteristics Timing (Using Douglas, MI coordinates) Cross-Period Collection Sunset videos span period boundaries: Current Script Advantage Your script already identifies golden hour segments: Append Strategy for Sunset Videos Challenge: &#8230; <a title=\"Revised timelapse method\" class=\"read-more\" href=\"https:\/\/scootercam.net\/blog\/revised-timelapse-method\/\" aria-label=\"Read more about Revised timelapse method\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-56","post","type-post","status-publish","format-standard","hentry","category-timelapse"],"_links":{"self":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/56","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/comments?post=56"}],"version-history":[{"count":1,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/56\/revisions"}],"predecessor-version":[{"id":57,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/56\/revisions\/57"}],"wp:attachment":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/media?parent=56"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/categories?post=56"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/tags?post=56"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}