Commit Graph
13 Commits
Author SHA1 Message Date
Mathieu MoranandCopilot cc6e9c8de0 feat: add download button to Pi videos list
- /api/local-video/file?download=1 serves file as attachment
- Download link (green DL button) added to each row in local-videos.js
- Dashcam USB files skipped: no persistent mount for direct serve;
  use Import then download from Pi Videos

Co-authored-by: Copilot <[email protected]>
2026-08-10 02:17:29 -04:00
Mathieu MoranandCopilot 1fde8732c2 fix(videos): stop thumbnails reloading on every convert poll
Instead of full re-render every 10s, patch converting badges in-place.
Only does a full renderFiles() when file count changes (conversion done)
or on the final poll when all conversions finish.

Co-authored-by: Copilot <[email protected]>
2026-08-10 01:49:03 -04:00
Mathieu MoranandCopilot d9d1537a13 feat(videos): show conversion progress % and elapsed time
- _converting dict now tracks started_at, source_size, tmp_path per file
- list_local_videos() reads tmp file size to compute pct complete
- Desktop badge: 'Converting 42% 1m30s'
- Mobile badge: '42%' (compact, fits under thumbnail)

Co-authored-by: Copilot <[email protected]>
2026-08-10 01:30:48 -04:00
Mathieu MoranandCopilot c995599512 feat(videos): add manual Convert button per MOV file on Pi
- New POST /api/local-video/convert route triggers queue_convert(force=True)
- queue_convert() now returns True/False/None and accepts force param
  to bypass the auto-convert toggle (manual always works)
- Convert button shown for non-MP4, non-converting files in video list
- Clicking spins the button and refreshes list after 1s to show badge

Co-authored-by: Copilot <[email protected]>
2026-08-10 01:28:56 -04:00
Mathieu MoranandCopilot ba712bd6db fix(dashcam): prevent site freeze during import/convert
- _convert_bg now runs in real threading.Thread (not gevent greenlet)
  so ffmpeg proc.wait() doesn't block gevent event loop
- _device_lock released before copy loop; only held for mount/unmount
  so /api/dash/files and other routes don't block during long copies
- Date now shows time (Aug 9, 10:30 PM) on mobile video rows
- Spacing added above converting spinner badge

Co-authored-by: Copilot <[email protected]>
2026-08-10 01:23:53 -04:00
Mathieu MoranandCopilot 77cd3fdadd feat(dashcam): show converting badge and date on mobile video rows
Co-authored-by: Copilot <[email protected]>
2026-08-10 01:18:03 -04:00
Mathieu MoranandCopilot 522674c907 fix(dashcam): remove inline width from thumb td, control via CSS with !important
Inline style.width on td was overriding the mobile media query width rule.
Use dash-thumb-td class for desktop (9rem) and mobile (5rem !important).

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:53:02 -04:00
Mathieu MoranandCopilot ba760a04d6 fix(dashcam): proper mobile row reflow + import status at top with ETA
- yaris.css: use .dash-row class on all rows; only td:first-child and
  .dash-actions-td visible on mobile (<576px); buttons never overflow
- dash.js: add dash-row class + dash-actions-td wrapper div to dashcam
  file rows; import status moved to card footer at top with spinner + ETA
- local-videos.js: add dash-row class to video rows
- dash.html: import status bar (spinner + ETA + result) in device card
  at top; removed old footer import status from files card

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:46:05 -04:00
Mathieu MoranandCopilot 01704d5429 feat(dashcam): mobile layout fix + optional hw-encode conversion on import
- yaris.css: on mobile (<576px) hide file/size/date/upload cols, show
  filename inside thumb cell, icon-only buttons, dash-actions-td nowrap
- local-videos.js: filename in thumb cell for mobile; Converting badge with
  spinner; auto-refresh every 10s while any file is converting
- app_video.py: CONVERT_SETTING, is_convert_enabled(), queue_convert(),
  _convert_bg() — h264_v4l2m2m + aac faststart, deletes original on success
- app_dash.py: call queue_convert() after each successful copy on import
- app_settings.py: expose video_convert_enabled in get/save settings
- settings.html: toggle for 'Convert imported videos for web playback'

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:30:59 -04:00
Mathieu MoranandCopilot 51322d0e00 fix(dashcam): wrap action buttons in div, ffmpeg stream for MOV playback
- local-videos.js: action buttons go in a div.data-list-actions inside td
  so td stays a table cell (not flex); thumbnail td gets fixed width 9rem
- app.py: video route now pipes ffmpeg with -c copy -movflags
  frag_keyframe+empty_moov so browsers get a fragmented MP4 stream that
  starts playing immediately without needing the moov atom at the end

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:17:10 -04:00
Mathieu MoranandCopilot 375b93fcea fix: restore /api/stats route, remove dead player code, fix modal scroll
- app_sql.py: add get_overview_stats() with single SQL query (trip count,
  total km, duration, max speed, active DTC count)
- app.py: add /api/stats route (was missing after scp overwrote the file)
- local-videos.js: remove leftover old closePlayer/playVideo/renderFiles
  duplicate block that still had scrollIntoView and references to the old
  panel elements; new modal-based code is the only path now

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:07:14 -04:00
Mathieu MoranandCopilot 600fd41353 fix(dashcam): range-request video streaming, modal player, async thumbnails
- app.py: replace send_file with manual Range-aware chunked generator;
  returns 206 on partial requests so browsers can seek/buffer properly.
  Thumbnail route returns 202 while ffmpeg is generating.
- app_video.py: thumbnail generation moved to background gevent greenlet
  (_generate_thumbnail_bg). get_thumbnail_path returns immediately with
  RuntimeError('generating') if not cached; ffmpeg only ever runs once
  per video (result cached in dash/thumbnails/).
- dash.html: replaced bottom card player with Bootstrap modal (modal-xl,
  centered, dark bg) — video pops up in place regardless of scroll position.
- local-videos.js: rewritten to use Bootstrap modal; thumbnail loader
  polls with fetch() and retries on 202 every 2s (up to 15x) instead of
  setting img.src directly (which can't detect 202).

Co-authored-by: Copilot <[email protected]>
2026-08-10 00:01:49 -04:00
Mathieu MoranandCopilot 3a981f5c6d Add local dashcam video library
Co-authored-by: Copilot <[email protected]>
2026-08-09 19:04:47 -04:00