Skip to content

A vanilla JavaScript media capture component that supports audio, video and photo.

Notifications You must be signed in to change notification settings

westguard/media-capture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MediaCapture

License: MIT JavaScript

A lightweight, flexible JavaScript library for injecting video, photo, and audio capture functionality into any DOM element. Built with vanilla JavaScript, no dependencies required.

Table of Contents

Features

  • Multiple Capture Modes: Video, photo, and audio recording
  • Camera Controls: Switch between front and rear cameras (where available)
  • Audio Input Selection: Choose from available microphones
  • Countdown Timer: Configurable countdown before capture starts with optional sound effects
  • Sound Effects: Support for custom audio files for countdown and shutter sounds
  • Pause/Resume: Video and audio pause/resume functionality
  • Customizable UI: Fully themeable with CSS variables
  • Event Callbacks: Comprehensive callback system for capture events
  • Public API: Direct control via public methods
  • Download Support: Built-in media download functionality
  • Settings Panel: UI for selecting cameras and microphones
  • Responsive Design: Mobile-friendly interface
  • Browser Compatibility: Works in modern browsers with getUserMedia support

Installation

Direct Download

Download the repository and include the files directly:

<link rel="stylesheet" href="dist/media-capture.css">
<script src="dist/media-capture.js"></script>

NPM

Note: This package is not yet published to npm. Coming soon!

# Not yet available
npm install media-capture

Quick Start

Basic Video Capture

<div id="capture-container"></div>

<script>
var container = document.getElementById('capture-container');

var capture = new MediaCapture(container, {
    mode: 'video',
    auto_start: false,
    
    on_video_captured: function(blob, filename, metadata) {
        console.log('Video captured!', filename, metadata);
    },
    
    on_error: function(error) {
        console.error('Error:', error);
    }
});
</script>

Basic Photo Capture

var capture = new MediaCapture(container, {
    mode: 'photo',
    
    on_photo_captured: function(blob, filename, metadata) {
        console.log('Photo captured!', filename, metadata);
    }
});

Basic Audio Capture

var capture = new MediaCapture(container, {
    mode: 'audio',
    max_duration: 30,
    
    on_audio_captured: function(blob, filename, metadata) {
        console.log('Audio captured!', filename, metadata);
    }
});

Configuration Options

Capture Settings

Option Type Default Description
mode string 'video' Capture mode: 'video', 'photo', or 'audio'
auto_start boolean false Automatically start camera/microphone on init
max_duration number 30 Maximum duration in seconds (video/audio only)
video_format string 'mp4' Video output format
audio_format string 'webm' Audio output format
photo_format string 'jpeg' Photo output format ('jpeg' or 'png')
photo_quality number 0.9 Photo compression quality (0-1)
facing_mode string 'user' Camera facing mode: 'user' or 'environment'
resolution string '' Requested resolution (e.g., '1280x720')
max_width string '' Maximum width of capture container (CSS)
controls_auto_hide boolean false Auto-hide controls during recording
controls_auto_hide_duration number 3000 Duration in milliseconds before controls auto-hide

Countdown Settings

Option Type Default Description
countdown_enabled boolean false Enable countdown timer before capture
countdown_duration number 3 Countdown duration in seconds
countdown_sound_enabled boolean false Play sound during countdown
countdown_sound_url string '' URL to custom countdown sound file

Audio Settings

Option Type Default Description
photo_sound_enabled boolean false Play sound when photo is captured
photo_sound_url string '' URL to custom photo/shutter sound file

UI Settings

Option Type Default Description
settings_download_enabled boolean false Show download button in settings panel
log boolean false Enable internal logging
log_to_console boolean true Log to browser console

Label Customization

All UI labels can be customized. Common labels:

Label Default
label_start_recording 'Start Recording'
label_stop 'Stop'
label_pause 'Pause'
label_resume 'Resume'
label_capture_photo 'Take Photo'
label_retake 'Retake Photo'
label_cancel_retake 'Cancel'
label_settings 'Settings'
label_flip_camera 'Flip Camera'
label_start_camera 'Start Camera'
label_start_microphone 'Start Microphone'
label_volume 'Volume'
label_progress 'Progress'

See the library for the complete list of customizable labels.

Callbacks

Video Callbacks

new MediaCapture(container, {
    on_video_captured: function(blob, filename, metadata) {
        // Called when video recording completes
    },
    
    on_video_started: function() {
        // Called when recording starts
    },
    
    on_video_stopped: function() {
        // Called when recording stops
    },
    
    on_video_paused: function() {
        // Called when recording is paused
    },
    
    on_video_resumed: function() {
        // Called when recording resumes
    },
    
    on_video_retake: function() {
        // Called when retake is initiated
    },
    
    on_video_cancel: function() {
        // Called when retake is cancelled
    }
});

Photo Callbacks

new MediaCapture(container, {
    on_photo_captured: function(blob, filename, metadata) {
        // Called when photo is captured
    },
    
    on_photo_retake: function() {
        // Called when retake is initiated
    },
    
    on_photo_cancel: function() {
        // Called when retake is cancelled
    }
});

Audio Callbacks

new MediaCapture(container, {
    on_audio_captured: function(blob, filename, metadata) {
        // Called when audio recording completes
    },
    
    on_audio_started: function() {
        // Called when recording starts
    },
    
    on_audio_stopped: function() {
        // Called when recording stops
    },
    
    on_audio_paused: function() {
        // Called when recording is paused
    },
    
    on_audio_resumed: function() {
        // Called when recording resumes
    },
    
    on_audio_retake: function() {
        // Called when retake is initiated
    },
    
    on_audio_cancel: function() {
        // Called when retake is cancelled
    }
});

UI & System Callbacks

new MediaCapture(container, {
    on_stream_started: function() {
        // Camera/microphone stream started
    },
    
    on_stream_stopped: function() {
        // Camera/microphone stream stopped
    },
    
    on_stream_flipped: function() {
        // Camera was flipped
    },
    
    on_settings_opened: function() {
        // Settings panel opened
    },
    
    on_settings_closed: function() {
        // Settings panel closed
    },
    
    on_result_show: function() {
        // Result preview shown
    },
    
    on_result_hide: function() {
        // Result preview hidden
    },
    
    on_cameras_detected: function(cameras) {
        // Array of available cameras detected
        // cameras is an array of MediaDeviceInfo objects
    },

    on_error: function(error) {
        // Error occurred
    },
    
    on_log: function(message, args, level) {
        // Custom logging callback
    }
});

Public Methods

Stream Control

capture.stream_start();     // Start camera/microphone
capture.stream_stop();      // Stop stream
capture.stream_flip();      // Flip camera (front/rear)

Recording Control

capture.video_start();      // Start video recording
capture.video_stop();       // Stop video recording
capture.video_pause();      // Pause video recording
capture.video_resume();     // Resume video recording
capture.video_retake();     // Show retake prompt
capture.video_cancel();     // Cancel retake

Photo Control

capture.photo_capture();    // Capture photo
capture.photo_retake();     // Show retake prompt
capture.photo_cancel();     // Cancel retake

Audio Control

capture.audio_start();      // Start audio recording
capture.audio_stop();       // Stop audio recording
capture.audio_pause();      // Pause audio recording
capture.audio_resume();     // Resume audio recording
capture.audio_retake();     // Show retake prompt
capture.audio_cancel();     // Cancel retake

Playback Control

capture.playback_play();    // Play captured video/audio
capture.playback_pause();   // Pause playback
capture.playback_stop();    // Stop playback
capture.playback_toggle();  // Toggle play/pause

Status Methods

capture.is_playing();       // Check if media is playing
capture.has_video();        // Check if video is captured
capture.has_photo();        // Check if photo is captured
capture.has_audio();        // Check if audio is captured

Media Access

capture.get_blob();         // Get media blob
capture.get_meta();         // Get media metadata
capture.download();         // Download media file

Settings

capture.settings_open();    // Open settings panel
capture.settings_close();   // Close settings panel

Utility Methods

capture.get_supported_formats();  // Get browser format support
// Returns: { audio: { webm: true, mp4: false, ... }, video: { webm: true, mp4: true, ... } }

Metadata Structure

When media is captured, callbacks receive a metadata object with details about the captured media:

Photo Metadata

{
    type: 'photo',
    width: 1920,           // Photo width in pixels
    height: 1080,          // Photo height in pixels
    size: 245678,          // File size in bytes
    format: 'jpeg',        // Photo format
    quality: 0.9,          // Compression quality
    timestamp: 1234567890, // Capture timestamp
    facing_mode: 'user'    // Camera facing mode used
}

Video Metadata

{
    type: 'video',
    size: 1234567,         // File size in bytes
    format: 'mp4',         // Video format
    duration: 15.3,        // Duration in seconds
    timestamp: 1234567890, // Capture timestamp
    resolution: '1280x720', // Resolution (if set)
    facing_mode: 'user'    // Camera facing mode used
}

Audio Metadata

{
    type: 'audio',
    size: 456789,          // File size in bytes
    format: 'webm',        // Audio format
    duration: 23.5,        // Duration in seconds
    timestamp: 1234567890, // Capture timestamp
    mime_type: 'audio/webm;codecs=opus' // Full MIME type
}

UI Events

The library dispatches custom events that can be listened to for UI state changes:

document.addEventListener('mc-ui-start-on', function() {
    // Start button enabled
});

document.addEventListener('mc-ui-start-off', function() {
    // Start button disabled
});

document.addEventListener('mc-ui-stop-on', function() {
    // Stop button enabled
});

document.addEventListener('mc-ui-pause-on', function() {
    // Pause button enabled
});

document.addEventListener('mc-ui-resume-on', function() {
    // Resume button enabled
});

document.addEventListener('mc-ui-retake-on', function() {
    // Retake button enabled
});

Customization with CSS Variables

Customize the appearance using CSS custom properties:

:root {
    /* Control colors */
    --mc-control-color-background: #f5f5f5;
    --mc-control-color: #333;
    --mc-control-color-record: #dc3545;
    --mc-control-color-level: #28a745;
    
    /* Control sizing */
    --mc-control-size: 40px;
    --mc-control-gap: 10px;
    
    /* Border styling */
    --mc-border: 1px solid #e0e0e0;
    --mc-border-radius: 8px;
    --mc-border-color-hover: #418FDE;
    --mc-border-color-focus: #418FDE;
    --mc-box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    
    /* Countdown styling */
    --mc-countdown-color: #333;
    --mc-countdown-color-background: rgba(0,0,0,0.8);
    --mc-countdown-font-size: 120px;
    --mc-countdown-font-weight: bold;
    
    /* Settings panel */
    --mc-settings-color: #333;
    --mc-settings-color-background: #ffffff;
}

Examples

The repository includes comprehensive examples:

Video Examples

  • Default Video - Basic video recording
  • Video Events - Programmatic control with external buttons
  • Video + Countdown - Countdown timer before recording
  • Video + Custom Styling - Customized appearance

Photo Examples

  • Default Photo - Basic photo capture
  • Photo Events - Programmatic control
  • Photo + Countdown + Sounds - Countdown and shutter sounds

Audio Examples

  • Default Audio - Basic audio recording
  • Audio Events - Programmatic control
  • Audio + Countdown - Countdown before recording
  • Audio + Custom Countdown - Custom countdown sound file

See the /examples directory for full implementation details.

Asset Files

Include optional sound effects from /assets/audio/:

  • beep-1.mp3 - Standard beep sound
  • beep-2.mp3 - Short sharp beep
  • beep-3.mp3 - Long sharp beep (suitable for shutter sound)
  • camera-shutter.mp3 - Camera shutter sound

Use these with countdown_sound_url and photo_sound_url options.

Troubleshooting

Camera/Microphone Access Issues

Problem: "Unable to access camera/microphone" error

Solutions:

  • Ensure your site is served over HTTPS (required by browsers for getUserMedia)
  • Check browser permissions - user must grant camera/microphone access
  • On mobile, check that no other app is using the camera
  • Try a different browser - some browsers have stricter policies
  • Clear browser cache and reload the page

Format Compatibility Issues

Problem: Recording doesn't work or files are corrupted

Solutions:

  • Use capture.get_supported_formats() to check browser support
  • Try a different format - use video_format: 'webm' if mp4 fails
  • Some browsers only support specific codecs
  • Safari has limited format support - WebM works best

Mobile Browser Issues

Problem: Camera flip doesn't work on mobile

Solutions:

  • Some devices only have one camera
  • Ensure proper permissions are granted
  • Try reloading the page after granting permissions

Problem: Video recording stops unexpectedly

Solutions:

  • Mobile browsers may limit recording duration
  • Check available storage space
  • Reduce max_duration for better reliability
  • Some browsers pause recording when tab loses focus

Performance Issues

Problem: Slow performance or high memory usage

Solutions:

  • Use lower resolution settings
  • Reduce photo_quality for smaller file sizes
  • Use minified version (media-capture.min.js)
  • Dispose of captured media when no longer needed
  • Call capture.destroy() when removing the instance

HTTPS Requirement

Modern browsers require HTTPS for accessing camera/microphone. For local development:

# Use a local HTTPS server
npx http-server -S -C cert.pem -K key.pem

Or use localhost which is treated as secure by most browsers.

Browser Support

Requires browsers with support for:

  • getUserMedia API
  • MediaRecorder API
  • Blob API
  • Promise support

Works in:

  • Chrome 49+
  • Firefox 29+
  • Safari 14.1+
  • Edge 15+
  • Opera 36+

Not supported in Internet Explorer.

Known Limitations

Browser API Limitations

  • MediaRecorder API Required: This library depends on the MediaRecorder API, which is not available in older browsers
  • Format Support Varies: Different browsers support different video/audio codecs. Use get_supported_formats() to check
  • Mobile Safari: Limited format support - prefer WebM for video, may fall back to different codecs
  • iOS Limitations: Some iOS versions have restrictions on camera access and recording duration

Feature Limitations

  • No Video Editing: Library captures raw video/audio/photo - no built-in editing capabilities
  • File Size: Large recordings may cause memory issues - monitor blob sizes for long recordings
  • No Streaming: Captures to Blob in memory - not designed for live streaming
  • Single Instance: While multiple instances are supported, only one camera stream per device at a time
  • Background Recording: Some mobile browsers pause recording when tab loses focus

Device Limitations

  • Camera Availability: Flip camera only works on devices with multiple cameras
  • Permissions: Browser will prompt for permissions - cannot be bypassed programmatically
  • HTTPS Required: Camera/microphone access requires secure context (HTTPS or localhost)
  • Mobile Constraints: Mobile devices may have lower recording quality or duration limits

Workarounds

Most limitations can be addressed by:

  • Testing format support with get_supported_formats()
  • Setting appropriate max_duration values
  • Handling errors gracefully with on_error callback
  • Providing user guidance about permissions
  • Using feature detection before initialization

Build

Build the project using the included build script:

npm install
npm run build

Watch for changes during development:

npm run watch

Contributing

Contributions are welcome! To contribute:

  1. Fork the repository on Bitbucket
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Make your changes
  4. Run the build (npm run build)
  5. Test your changes with the examples
  6. Commit your changes (git commit -am 'Add new feature')
  7. Push to the branch (git push origin feature/my-feature)
  8. Create a Pull Request

Please ensure your code:

  • Follows the existing code style (snake_case for functions)
  • Includes comments for complex logic
  • Works across all supported browsers
  • Doesn't break existing examples

License

MIT License

Copyright (c) 2025 Westguard Solutions

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Support

For issues, questions, or feature requests, please use the issue tracker on the Bitbucket repository.

Notes for WordPress Integration

This library is designed to work well with WordPress:

  • Self-contained, no external dependencies
  • Vanilla JavaScript compatible with WordPress enqueue system
  • Can be easily enqueued as a plugin or theme asset
  • Use snake_case for function names to follow WordPress conventions
  • Compatible with both classic and block editor environments
  • Works with custom Gutenberg blocks
  • No conflicts with popular WordPress plugins

Example WordPress enqueue:

wp_enqueue_script('media-capture', plugin_dir_url(__FILE__) . 'dist/media-capture.js', array(), '1.0.0', true);
wp_enqueue_style('media-capture', plugin_dir_url(__FILE__) . 'dist/media-capture.css', array(), '1.0.0');

About

A vanilla JavaScript media capture component that supports audio, video and photo.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published