{"id":16641154,"url":"https://github.com/suminb/cctv","last_synced_at":"2026-04-14T18:31:48.917Z","repository":{"id":4184492,"uuid":"5301676","full_name":"suminb/cctv","owner":"suminb","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-16T14:03:58.000Z","size":73,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-16T15:59:57.615Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/suminb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2012-08-05T07:25:11.000Z","updated_at":"2026-02-16T08:42:02.000Z","dependencies_parsed_at":"2022-08-20T14:20:16.039Z","dependency_job_id":null,"html_url":"https://github.com/suminb/cctv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/suminb/cctv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suminb%2Fcctv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suminb%2Fcctv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suminb%2Fcctv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suminb%2Fcctv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/suminb","download_url":"https://codeload.github.com/suminb/cctv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suminb%2Fcctv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31810737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"ssl_error","status_checked_at":"2026-04-14T18:05:01.765Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T07:45:29.459Z","updated_at":"2026-04-14T18:31:48.912Z","avatar_url":"https://github.com/suminb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CCTV Archiver\n\nA Python application that archives RTSP video streams by:\n- Capturing live RTSP streams and saving them as HLS segments\n- Consolidating hourly segments into MP4 files using H.265 codec\n- Automatically cleaning up old archived files based on retention period\n\n## Features\n\n- **Continuous Recording**: Captures RTSP streams 24/7 with automatic crash recovery\n- **Hourly Consolidation**: Converts HLS segments to compressed MP4 files every hour\n- **Automatic Cleanup**: Removes archived files older than the configured retention period\n- **Graceful Shutdown**: Handles termination signals to ensure clean process shutdown\n\n## Configuration\n\nThe application is configured using environment variables:\n\n- `RTSP_URL` (required): The RTSP stream URL to capture\n- `ARCHIVE_PATH` (optional): Directory path for storing archived files (default: `/archive`)\n- `RETENTION_DAYS` (optional): Number of days to keep archived files (default: 90)\n\n## Running the Application\n\n### Using Docker\n\nBuild the Docker image:\n\n```bash\ndocker build -t cctv-archiver .\n```\n\nRun the container:\n\n```bash\ndocker run -d \\\n  -e RTSP_URL=\"rtsp://your-camera-url\" \\\n  -e ARCHIVE_PATH=\"/archive\" \\\n  -e RETENTION_DAYS=90 \\\n  -v /path/to/local/archive:/archive \\\n  --name cctv-archiver \\\n  cctv-archiver\n```\n\n### Pushing to Private Registry\n\nIf you need to push the image to a private Docker registry (e.g., `zot.whiterabbit.co.kr`):\n\n```bash\n# Build the image\ndocker build -t zot.whiterabbit.co.kr/app/cctv:latest .\n\n# Tag with specific version/commit\ndocker tag zot.whiterabbit.co.kr/app/cctv:latest zot.whiterabbit.co.kr/app/cctv:$(git rev-parse --short HEAD)\n\n# Log in to the registry\ndocker login zot.whiterabbit.co.kr\n\n# Push the images\ndocker push zot.whiterabbit.co.kr/app/cctv:latest\ndocker push zot.whiterabbit.co.kr/app/cctv:$(git rev-parse --short HEAD)\n```\n\n### Running Locally (without Docker)\n\nEnsure you have Python 3 and ffmpeg installed, then run:\n\n```bash\nexport RTSP_URL=\"rtsp://your-camera-url\"\nexport ARCHIVE_PATH=\"/path/to/archive\"\nexport RETENTION_DAYS=90\npython3 app.py\n```\n\n## Maintenance Commands\n\n### Purge Leftover HLS Files\n\nWhen an MP4 archive is successfully created from HLS segments, the source .ts and .m3u8 files are automatically deleted. However, if this automatic cleanup fails (e.g., due to file permissions or other errors), these files may remain in the archive directory.\n\nThe `purge` command cleans up HLS files that should have been deleted after successful consolidation:\n\n```bash\nexport ARCHIVE_PATH=\"/path/to/archive\"\npython3 app.py purge\n```\n\nThis command will:\n- Scan the archive directory for all MP4 files\n- Identify HLS files (.ts and .m3u8) that **have** corresponding MP4 archives (meaning they should have been deleted already)\n- **Exclude files from the current hour and previous 2 hours** (to protect actively recording or consolidating files)\n- Delete the leftover HLS files and report how much space was freed\n\n**Note**: The purge command only deletes HLS files that have corresponding MP4 archives AND are older than 3 hours. This ensures that:\n- Files still being recorded are never deleted\n- Files in the consolidation queue are protected\n- Only leftover files from failed cleanup operations are removed\n\n## Testing\n\nRun the unit tests:\n\n```bash\npython3 -m unittest test_app.py\n```\n\n## CI/CD\n\nThe repository includes a GitHub Actions CI pipeline that:\n- Runs unit tests on every push and pull request\n- Validates the code works on Python 3.x\n\nNote: Docker image building and pushing is not automated in the CI pipeline because the target registry is in a private network. Images should be built and pushed manually from within the private network as shown above.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuminb%2Fcctv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuminb%2Fcctv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuminb%2Fcctv/lists"}