npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

why-converter

v1.0.0

Published

Why would you ever use this? A universal library for converting videos to PDF, GIF, or image sequences with advanced frame extraction options

Readme

Why Converter

"Why would you ever use this?"

A powerful, universal JavaScript library for converting videos to PDF, GIF, or image sequences.

Features

  • Multiple Output Formats: PDF, GIF, or image sequences (PNG, JPEG, WebP)
  • Flexible Frame Extraction: Extract by frame count, frame interval, or time interval
  • PDF Layouts: Customise frames per page, page size, and orientation
  • Quality Control: Adjust compression, dimensions, and quality settings
  • Universal: Works in both Node.js and browser environments
  • Zero Config: Sensible defaults with extensive customization options
  • Progress Tracking: Monitor conversion progress with callbacks
  • Format Support: MP4, WebM, MOV, AVI, MKV (Node.js) | MP4, WebM, OGG (Browser)

Installation

npm install why-converter

For Node.js usage, you'll also need ffmpeg installed on your system, or use the optional ffmpeg-static package:

npm install why-converter ffmpeg-static

Quick Start

Node.js

const { convertVideo } = require('why-converter');

// Convert video to PDF
const result = await convertVideo('./video.mp4', {
  extractionMode: 'frames',
  framesCount: 10,
  outputFormat: 'pdf',
  outputPath: './output.pdf',
  onProgress: (progress) => console.log(`${progress}%`)
});

console.log('Success!', result);

Browser

<script src="node_modules/why-converter/dist/browser/index.js"></script>

<script>
  const fileInput = document.querySelector('input[type="file"]');
  
  fileInput.addEventListener('change', async (e) => {
    const result = await WhyConverter(e.target.files[0], {
      extractionMode: 'frames',
      framesCount: 10,
      outputFormat: 'pdf',
      onProgress: (progress) => console.log(`${progress}%`)
    });
    
    // Download the PDF
    const url = URL.createObjectURL(result.blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'output.pdf';
    a.click();
  });
</script>

API Reference

convertVideo(input, options)

Main function to convert videos.

Parameters

  • input: string | File | Blob | Buffer

    • File path (Node.js) or File/Blob object (Browser)
  • options: ConversionOptions object with the following properties:

Frame Extraction Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | extractionMode | 'frames' \| 'interval' \| 'time' | 'frames' | Frame extraction mode | | framesCount | number | 10 | Number of frames to extract (mode: 'frames') | | frameInterval | number | - | Extract every Nth frame (mode: 'interval') | | timeInterval | number | - | Extract frame every N seconds (mode: 'time') |

Output Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | outputFormat | 'pdf' \| 'gif' \| 'images' | 'pdf' | Output format | | outputPath | string | - | Output file path (Node.js only) |

PDF Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | pdfLayout | 'portrait' \| 'landscape' | 'landscape' | Page orientation | | framesPerPage | number | 1 | Number of frames per page | | pageSize | 'A4' \| 'Letter' \| 'Legal' \| [width, height] | 'A4' | PDF page size |

GIF Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | gifFps | number | 10 | Frames per second | | gifQuality | number | 80 | Quality (1-100) | | gifRepeat | number | 0 | Loop count (0 = infinite) |

Image Sequence Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | imageFormat | 'png' \| 'jpeg' \| 'webp' | 'png' | Image format | | imageQuality | number | 90 | Quality for JPEG/WebP (1-100) | | imagePrefix | string | 'frame_' | Filename prefix |

Quality Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | width | number | - | Output width in pixels | | height | number | - | Output height in pixels | | maintainAspectRatio | boolean | true | Maintain aspect ratio | | compression | number | 80 | Compression level (0-100) |

Callbacks

| Option | Type | Description | |--------|------|-------------| | onProgress | (progress: number) => void | Progress callback (0-100) | | onComplete | (result: ConversionResult) => void | Completion callback | | onError | (error: Error) => void | Error callback |

Returns

Promise<ConversionResult> with:

{
  success: boolean;
  outputPath?: string;        // Node.js
  blob?: Blob;                // Browser (PDF/GIF)
  files?: File[];             // Browser (images)
  metadata: {
    totalFrames: number;
    extractedFrames: number;
    duration: number;
    dimensions: { width: number; height: number };
  };
}

Examples

Example 1: Video to PDF (Multiple Frames Per Page)

const result = await convertVideo('./video.mp4', {
  extractionMode: 'time',
  timeInterval: 2,              // Extract frame every 2 seconds
  outputFormat: 'pdf',
  framesPerPage: 4,             // 2x2 grid
  pdfLayout: 'landscape',
  pageSize: 'A4'
});

Example 2: Video to GIF Animation

const result = await convertVideo('./video.mp4', {
  extractionMode: 'frames',
  framesCount: 30,
  outputFormat: 'gif',
  gifFps: 15,
  gifQuality: 90,
  width: 640,                   // Resize to 640px width
  maintainAspectRatio: true
});

Example 3: Extract Image Sequence

const result = await convertVideo('./video.mp4', {
  extractionMode: 'interval',
  frameInterval: 30,            // Every 30th frame
  outputFormat: 'images',
  imageFormat: 'jpeg',
  imageQuality: 85,
  imagePrefix: 'scene_'
});

Example 4: Extract Key Moments

const result = await convertVideo('./video.mp4', {
  extractionMode: 'frames',
  framesCount: 12,
  outputFormat: 'pdf',
  framesPerPage: 6,
  pdfLayout: 'portrait',
  pageSize: 'Letter'
});

Example 5: Browser with Progress Bar

const progressBar = document.getElementById('progress');

const result = await VideoFrameConverter(videoFile, {
  extractionMode: 'frames',
  framesCount: 20,
  outputFormat: 'pdf',
  onProgress: (progress) => {
    progressBar.style.width = `${progress}%`;
  }
});

// Download result
const url = URL.createObjectURL(result.blob);
const a = document.createElement('a');
a.href = url;
a.download = 'output.pdf';
a.click();

Use Cases

  • Video Documentation: Create PDF reports from video content
  • Educational Materials: Extract key frames for study guides
  • Storyboarding: Generate storyboards from video footage
  • Thumbnails: Extract preview images from videos
  • Video Analysis: Create visual timelines of video content
  • Animation: Convert video clips to GIF animations
  • Frame Extraction: Batch extract frames for processing

Requirements

Node.js

  • Node.js >= 14.0.0
  • FFmpeg (installed globally or via ffmpeg-static package)

Browser

  • Modern browser with:
    • HTML5 Video API
    • Canvas API
    • Blob/File API
    • Supports: Chrome, Firefox, Safari, Edge

Advanced Configuration

Custom Page Sizes

const result = await convertVideo('./video.mp4', {
  outputFormat: 'pdf',
  pageSize: [800, 1200],        // Custom size in points
  framesPerPage: 1
});

Custom Dimensions

const result = await convertVideo('./video.mp4', {
  width: 1920,
  height: 1080,
  maintainAspectRatio: false    // Force exact dimensions
});

All Callbacks

const result = await convertVideo('./video.mp4', {
  extractionMode: 'frames',
  framesCount: 10,
  outputFormat: 'pdf',
  onProgress: (progress) => {
    console.log(`Progress: ${progress.toFixed(2)}%`);
  },
  onComplete: (result) => {
    console.log('Complete!', result.metadata);
  },
  onError: (error) => {
    console.error('Failed:', error.message);
  }
});

Troubleshooting

FFmpeg Not Found (Node.js)

Install ffmpeg globally or use ffmpeg-static:

npm install ffmpeg-static

Browser Memory Issues

For large videos, reduce the number of frames extracted:

const result = await convertVideo(videoFile, {
  extractionMode: 'frames',
  framesCount: 10,              // Fewer frames
  width: 640                    // Smaller dimensions
});

CORS Issues in Browser

Ensure your video files are served with proper CORS headers if loading from external URLs.

TypeScript Support

Full TypeScript definitions are included:

import { convertVideo, ConversionOptions, ConversionResult } from 'why-converter';

const options: ConversionOptions = {
  extractionMode: 'frames',
  framesCount: 10,
  outputFormat: 'pdf'
};

const result: ConversionResult = await convertVideo('./video.mp4', options);

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details

Acknowledgments

🔗 Links


Made with ❤️ by Ya boi