{"id":73,"date":"2025-08-28T02:21:55","date_gmt":"2025-08-28T02:21:55","guid":{"rendered":"https:\/\/scootercam.net\/notes\/?p=73"},"modified":"2025-08-28T02:21:55","modified_gmt":"2025-08-28T02:21:55","slug":"timelapseversion-563549","status":"publish","type":"post","link":"https:\/\/scootercam.net\/blog\/timelapseversion-563549\/","title":{"rendered":"Timelapse,version 563,549"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Automated Timelapse System<\/h1>\n\n\n\n<p>A distributed timelapse video system using Raspberry Pi capture nodes and centralized video processing. Produces continuous daily timelapse videos from multiple camera angles with automatic golden hour detection.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Features<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Multi-camera support<\/strong> &#8211; Currently configured for 2 IP cameras (Amcrest, Reolink)<\/li>\n\n\n\n<li><strong>Automatic video compilation<\/strong> &#8211; Real-time appending of video segments to daily files<\/li>\n\n\n\n<li><strong>Golden hour detection<\/strong> &#8211; Separate sunset videos using astronomical calculations<\/li>\n\n\n\n<li><strong>Staggered processing<\/strong> &#8211; Camera uploads separated by 30 seconds to prevent server overload<\/li>\n\n\n\n<li><strong>Period-based organization<\/strong> &#8211; Day (8am-4pm), Evening (4pm-12am), Night (12am-8am) periods<\/li>\n\n\n\n<li><strong>Location-aware<\/strong> &#8211; Sunset timing automatically adjusts for Douglas, Michigan coordinates<\/li>\n\n\n\n<li><strong>Resilient uploads<\/strong> &#8211; Retry logic with proper error handling<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">System Architecture<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Raspberry Pi (Capture Node)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Image capture<\/strong> &#8211; RTSP stream capture every 15 seconds<\/li>\n\n\n\n<li><strong>Video processing<\/strong> &#8211; FFmpeg compilation of images into 15-minute segments<\/li>\n\n\n\n<li><strong>Upload client<\/strong> &#8211; cURL-based segment delivery to processing server<\/li>\n\n\n\n<li><strong>Staggered execution<\/strong> &#8211; Cameras process 30 seconds apart<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Server (Processing Node)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Segment receiver<\/strong> &#8211; PHP-based upload handler<\/li>\n\n\n\n<li><strong>Video appending<\/strong> &#8211; FFmpeg concatenation of segments to daily videos<\/li>\n\n\n\n<li><strong>Period management<\/strong> &#8211; Automatic video rotation every 8 hours<\/li>\n\n\n\n<li><strong>Golden hour calculation<\/strong> &#8211; Astronomical sunset timing for special footage<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Requirements<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Raspberry Pi<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Python 3.7+<\/li>\n\n\n\n<li>FFmpeg 4.0+<\/li>\n\n\n\n<li>RTSP-capable IP cameras<\/li>\n\n\n\n<li>Reliable network connection<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Server<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP 7.4+ with file upload support<\/li>\n\n\n\n<li>FFmpeg 4.0+<\/li>\n\n\n\n<li>Web server (Apache\/Nginx)<\/li>\n\n\n\n<li>Sufficient storage (2-5GB per day)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Installation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Raspberry Pi Setup<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Clone repository\ngit clone https:\/\/github.com\/username\/timelapse-system.git\ncd timelapse-system\n\n# Create Python virtual environment\npython3 -m venv venv\nsource venv\/bin\/activate\npip install -r requirements.txt\n\n# Configure cameras and server\ncp config.py.example config.py\n# Edit config.py with your camera URLs and server details\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Server Setup<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Copy PHP handler to web directory\ncp upload.php \/var\/www\/html\/timelapse\/\n\n# Create required directories\nmkdir -p \/var\/www\/html\/timelapse\/videos\nmkdir -p \/var\/www\/html\/timelapse\/temp\nchmod 755 \/var\/www\/html\/timelapse\/videos\nchmod 755 \/var\/www\/html\/timelapse\/temp\n\n# Ensure PHP can write to directories\nchown -R www-data:www-data \/var\/www\/html\/timelapse\/\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Configuration<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">config.py (Raspberry Pi)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>CAMERAS = {\n    'amcrest': {\n        'rtsp_url': 'rtsp:\/\/admin:password@192.168.1.100\/stream',\n        'name': 'amcrest',\n        'stagger_offset': 0,  # Process at :00 seconds\n        'enabled': True\n    },\n    'reolink': {\n        'rtsp_url': 'rtsp:\/\/admin:password@192.168.1.101\/stream', \n        'name': 'reolink',\n        'stagger_offset': 30,  # Process at :30 seconds\n        'enabled': True\n    }\n}\n\nSERVER_CONFIG = {\n    'upload_url': 'http:\/\/yourserver.com\/timelapse\/upload.php',\n    'upload_retries': 3,\n    'upload_timeout': 300\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Geographic Configuration<\/h3>\n\n\n\n<p>Update coordinates in <code>upload.php<\/code> for accurate sunset calculation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private $latitude = 42.5596;  \/\/ Your latitude\nprivate $longitude = -86.2355; \/\/ Your longitude\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Usage<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Start Raspberry Pi System<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Run as service (recommended)\nsudo systemctl enable timelapse\nsudo systemctl start timelapse\n\n# Or run manually\ncd \/path\/to\/timelapse\npython3 main.py\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Monitor System<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Check logs\ntail -f \/home\/pi\/timelapse\/logs\/timelapse_*.log\n\n# View system status\ncurl http:\/\/yourserver.com\/timelapse\/upload.php?action=status\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Manual Operations<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Force video rebuild\ncurl http:\/\/yourserver.com\/timelapse\/upload.php?action=rebuild&amp;camera=amcrest&amp;type=day\n\n# Archive current videos  \ncurl http:\/\/yourserver.com\/timelapse\/upload.php?action=rotate\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">File Structure<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>timelapse-system\/\n\u251c\u2500\u2500 main.py                 # Main controller\n\u251c\u2500\u2500 process_segments.py     # Video processing script\n\u251c\u2500\u2500 config.py              # Configuration\n\u251c\u2500\u2500 upload.php             # Server upload handler\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 systemd\/\n    \u2514\u2500\u2500 timelapse.service   # Systemd service file\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">API Endpoints<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">POST \/upload.php<\/h3>\n\n\n\n<p>Upload video segment for processing<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Parameters<\/strong>: camera, video file, timestamp, size<\/li>\n\n\n\n<li><strong>Response<\/strong>: JSON with status and video update info<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">GET \/upload.php?action=status<\/h3>\n\n\n\n<p>Get system status and video information<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GET \/upload.php?action=rotate<\/h3>\n\n\n\n<p>Archive current videos and start fresh daily files<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Daily Output<\/h2>\n\n\n\n<p>The system produces 8 video files per day:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>{camera}_day_{YYYYMMDD}.mp4<\/code> &#8211; Daytime footage (8am-4pm)<\/li>\n\n\n\n<li><code>{camera}_evening_{YYYYMMDD}.mp4<\/code> &#8211; Evening footage (4pm-12am)<\/li>\n\n\n\n<li><code>{camera}_night_{YYYYMMDD}.mp4<\/code> &#8211; Overnight footage (12am-8am)<\/li>\n\n\n\n<li><code>{camera}_sunset_{YYYYMMDD}.mp4<\/code> &#8211; Golden hour footage (sunset \u00b130min)<\/li>\n<\/ul>\n\n\n\n<p>Videos update in real-time as segments arrive throughout the day.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Performance<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Processing time<\/strong>: ~2-3 seconds per segment<\/li>\n\n\n\n<li><strong>Storage usage<\/strong>: ~2-5GB per camera per day<\/li>\n\n\n\n<li><strong>Network bandwidth<\/strong>: ~50KB per segment upload<\/li>\n\n\n\n<li><strong>Server load<\/strong>: Minimal (stream copy operations only)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Common Issues<\/h3>\n\n\n\n<p><strong>No uploads reaching server<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check network connectivity and server URL<\/li>\n\n\n\n<li>Verify camera RTSP streams are accessible<\/li>\n\n\n\n<li>Review Raspberry Pi logs for processing errors<\/li>\n<\/ul>\n\n\n\n<p><strong>FFmpeg append failures<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ensure server has write permissions to video directories<\/li>\n\n\n\n<li>Check FFmpeg installation and version compatibility<\/li>\n\n\n\n<li>Review PHP error logs for specific FFmpeg error messages<\/li>\n<\/ul>\n\n\n\n<p><strong>Timing\/stagger issues<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify system clocks are synchronized (NTP)<\/li>\n\n\n\n<li>Check configuration stagger_offset values<\/li>\n\n\n\n<li>Monitor controller logs for trigger timing<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Contributing<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Fork the repository<\/li>\n\n\n\n<li>Create a feature branch<\/li>\n\n\n\n<li>Make your changes with appropriate tests<\/li>\n\n\n\n<li>Submit a pull request with clear description<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">License<\/h2>\n\n\n\n<p>MIT License &#8211; See LICENSE file for details<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Support<\/h2>\n\n\n\n<p>For issues and questions, please create a GitHub issue with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>System information (Pi model, server OS, versions)<\/li>\n\n\n\n<li>Relevant log excerpts<\/li>\n\n\n\n<li>Clear description of expected vs actual behavior<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Automated Timelapse System A distributed timelapse video system using Raspberry Pi capture nodes and centralized video processing. Produces continuous daily timelapse videos from multiple camera angles with automatic golden hour detection. Features System Architecture Raspberry Pi (Capture Node) Server (Processing Node) Requirements Raspberry Pi Server Installation Raspberry Pi Setup Server Setup Configuration config.py (Raspberry Pi) &#8230; <a title=\"Timelapse,version 563,549\" class=\"read-more\" href=\"https:\/\/scootercam.net\/blog\/timelapseversion-563549\/\" aria-label=\"Read more about Timelapse,version 563,549\">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":[1],"tags":[],"class_list":["post-73","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/73","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=73"}],"version-history":[{"count":1,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":74,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/posts\/73\/revisions\/74"}],"wp:attachment":[{"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/media?parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/categories?post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scootercam.net\/blog\/wp-json\/wp\/v2\/tags?post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}