Total Posts

0

Total Commits

0

(v1: 0, v2: 0)
Total Deployments

0

Latest commit:Unable to fetch commit info
6/22/2025
Latest deployment:
pending
6/22/2025
v2
Started 6/22/2025

Built by Remco Stoeten with a little ❤️

Snippets.remcostoeten
Snippets.remcostoeten
Snippets
Welcome to Snippets
Disable Sudo Password Prompts on macOS
Disable Sudo Password Prompts on macOS
Validate env variables
Drizzle ORM Schema Design
Setup Drizzle ORM with SQLite
Keybindings remap
Keyboard Tester Feature Prompt
Microphone Tester Feature Prompt
Webcam Tester
Practical Electron + Prisma Integration Guide
Complete Electron + Prisma Integration Guide
Git Branch Diverged
Git Set Upstream
Text Formatting Components
Suspense Wrapper Guide for SSR and Client UX
Features

Webcam Tester

Build a Webcam Testing Component in a Next.js App Router app with the following capabilities, UI behaviors, and data model. It should function independently but follow the same structure as the microphone testing feature.

📷 Webcam Detection & Access

  • Detect and list all connected webcams
    • Show their device names or fallback to Unknown Webcam
  • Handle all permission/access states:
    • ❌ Empty state → no webcams detected
    • 🚫 Denied state → user blocked camera access, show instructions
    • ⚠️ Error state → unknown issue fallback

🔴 Live Webcam Preview

  • Show a live video feed from the selected webcam
    • Allow user to select a different device from a dropdown if multiple are present
  • Indicate which device is currently active

🎥 Recording Interface

  • Controls:

    • Start, Pause, Resume, Stop recording
    • Timer works just like mic version:
      • Starts at 0s
      • Pauses and resumes correctly
  • After stopping:

    • Display a video player preview
    • Allow download as MP4 or WebM
  • Support for multiple recordings

    • Each recording shows:
      • Editable title (Recording - <timestamp>)
      • Video thumbnail preview (from 1s in)
      • Play/pause controls
      • Seek by clicking timeline
      • Delete and download buttons

⚙️ Playback Controls

  • Skip ±5s buttons (with boundaries)
  • Playback speed options:
    • Slow: 0.25x, 0.5x, 0.75x
    • Fast: 1.25x, 1.5x, 1.75x, 2x
  • Toggle playback loop mode

♿ Accessibility

  • All controls must be:
    • Fully keyboard accessible
    • Aria-labeled
    • Have clear focus states
  • Hotkeys:
    • Space = play/pause
    • R = record
    • B/F = skip 5s backward/forward

💾 Storage & Persistence

  • Data is stored in localStorage for now
    • Should persist on reload
  • Later stored in PostgreSQL via Drizzle ORM

🧱 Data Model — LocalStorage

type WebcamRecording = {
  id: string; // UUID
  title: string;
  deviceLabel: string;
  createdAt: string; // ISO
  updatedAt: string;
  duration: number; // in seconds
  videoBlobUrl: string; // Object URL
  thumbnailUrl: string; // snapshot from video
  playbackRate: number;
};

Example JSON

[
  {
    "id": "70fdfb88-4880-49f4-b189-bcf4c354d841",
    "title": "Recording - 2025-04-13 15:44",
    "deviceLabel": "Logitech C920 HD",
    "createdAt": "2025-04-13T15:44:02.000Z",
    "updatedAt": "2025-04-13T15:44:02.000Z",
    "duration": 19,
    "videoBlobUrl": "blob:http://localhost:3000/video1234",
    "thumbnailUrl": "blob:http://localhost:3000/thumb1234",
    "playbackRate": 1.0
  }
]

Utility for LocalStorage

localStorage.setItem("webcam-recordings", JSON.stringify(recordings));
const recordings = JSON.parse(
  localStorage.getItem("webcam-recordings") ?? "[]"
) as WebcamRecording[];

🐘 PostgreSQL Schema with Drizzle ORM

Schema

import {
  pgTable,
  text,
  uuid,
  timestamp,
  real,
  integer,
} from "drizzle-orm/pg-core";
 
export const webcamRecordings = pgTable("webcam_recordings", {
  id: uuid("id").primaryKey().defaultRandom(),
  title: text("title").notNull(),
  deviceLabel: text("device_label"),
  createdAt: timestamp("created_at", { mode: "date" }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { mode: "date" }).notNull().defaultNow(),
  duration: integer("duration").notNull(),
  videoUrl: text("video_url").notNull(), // base64 or public URL
  thumbnailUrl: text("thumbnail_url").notNull(),
  playbackRate: real("playback_rate").default(1.0),
});

Notes:

  • videoUrl can be:
    • A base64 string
    • Or an uploaded URL (Supabase, S3, etc.)
  • thumbnailUrl is a snapshot from the video for preview
  • This model supports hydration from localStorage

Let me know if you want:

  • 📤 A migration tool from localStorage to Postgres
  • 🧑‍🎨 A UI sketch using Shadcn components
  • 🖥️ A "device tester" dashboard that combines mic + cam + speakers

Microphone Tester Feature Prompt

A feature prompt for the Microphone Tester component which I still want to implement for my pheripherals tester tool.

Practical Electron + Prisma Integration Guide

A practical, example-driven guide for integrating Prisma with Electron, featuring a real-world task management system

On this page

📷 Webcam Detection & Access🔴 Live Webcam Preview🎥 Recording Interface⚙️ Playback Controls♿ Accessibility💾 Storage & Persistence🧱 Data Model — LocalStorageExample JSONUtility for LocalStorage🐘 PostgreSQL Schema with Drizzle ORMSchemaNotes:
Jun 22, 2025
2 min read
302 words