Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save DHANRAJCHOUDHARY244/bc3eb1effae93a6005b5b98979427d4d to your computer and use it in GitHub Desktop.
Save DHANRAJCHOUDHARY244/bc3eb1effae93a6005b5b98979427d4d to your computer and use it in GitHub Desktop.

Introduction

This project implements a dynamic file upload and serving mechanism based on the user's internet speed. It uses Node.js for the server-side logic and Angular for the client-side logic. The server utilizes speedtest-net to check the user's internet speed in real-time and express-fileupload for file uploads. Files are compressed using sharp and then uploaded to AWS S3 using the aws-sdk. The client-side logic determines the appropriate file version to serve based on the user's internet speed.

Package used

  • SHARP for compress image
  • speedtest-net for realtime speed check
  • express-fileupload
  • aws-sdk

Table of contents

package used

  • SHARP for compress image
  • speedtest-net for realtime speed check
  • express-fileupload
  • aws-sdk

SERVER SIDE LOGIC

Speed test check

const speedTest = require('speedtest-net');

app.get('/internet-speed', async (req, res) => {
    try {
        const { speeds } = await speedTest();

        // Convert speed to KBps
        const speedKBps = Math.round(speeds.download / 1024);

        res.json({ speed: speedKBps });
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: 'Failed to get internet speed' });
    }
});

File upload Logic

const express = require('express');
const fileUpload = require('express-fileupload');
const sharp = require('sharp');
const AWS = require('aws-sdk');

const app = express();

app.use(fileUpload());

// API endpoint to upload media file
app.post('/upload', async (req, res) => {
    try {
        const file = req.files.file;

        const sizes = [20, 40, 60, 80, 100];
        const versions = await Promise.all(sizes.map(async size => {
            const resizedImage = await sharp(file.data)
                                   .resize({ width: Math.floor(file.size * (size / 100)) })
                                      .toBuffer();
            const s3 = new AWS.S3({
                accessKeyId: 'YOUR_ACCESS_KEY_ID',
                secretAccessKey: 'YOUR_SECRET_ACCESS_KEY'
            });
            const params = {
                Bucket: 'YOUR_BUCKET_NAME',
                Key: `${file.name}_${size}.jpg`,
                Body: resizedImage
            };
            await s3.upload(params).promise();
            return `http://yourcdn.com/${file.name}_${size}.jpg`;
        }));

        res.json({ message: 'File uploaded successfully', versions });
    } catch (error) {
        console.error(error);
        res.status(500).json({ error: 'Failed to upload file' });
    }
});

Client Side logic

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class InternetSpeedService {
    constructor(private http: HttpClient) {}

    getInternetSpeed(): Observable<number> {
        return this.http.get<number>('http://your-node-server/internet-speed');
    }

    getMediaUrlBasedOnSpeed(url20: string, url40: string, url60: string, url80: string, url100: string): Observable<string> {
        return new Observable(observer => {
            this.getInternetSpeed().subscribe(speed => {
                let selectedUrl: string;

                if (speed < 50) { // less than 50 KBps
                    selectedUrl = url20;
                } else if (speed < 200) { // between 50 and 200 KBps
                    selectedUrl = url40;
                } else if (speed < 500) { // between 200 and 500 KBps
                    selectedUrl = url60;
                } else if (speed < 1000) { // between 500 KBps and 1 MBps
                    selectedUrl = url80;
                } else { // greater than 1 MBps
                    selectedUrl = url100;
                }

                observer.next(selectedUrl);
                observer.complete();
            });
        });
    }
}

Other advanced tool like

  • image-and-video-compressor
    • Git hub repo
    • This package wouldn't be possible without the following awesome libraries:
      • sharp - High-performance Node.js image processing.
      • fluent-ffmpeg - A fluent API to FFMPEG.

Sure! Here's a small README.md file you can add to your project to explain the video compression code and the codecs:





Video Compression using FFmpeg

This Node.js script demonstrates how to compress a video file using FFmpeg with support for two different codecs: AV1 and H.264.

Installation

  1. Install FFmpeg and FFmpeg utilities in your Node.js project:

    npm install @ffmpeg/ffmpeg @ffmpeg/util
  2. Run the Node.js script to compress videos using different codecs.

Code

  • compress_video.js

const { exec } = require('@ffmpeg/ffmpeg');

async function compressVideo(inputPath, outputPath, codec) {
  try {
    let codecFlag = '';
    if (codec === 'av1') {
      codecFlag = '-c:v libaom-av1 -strict experimental';
    } else if (codec === 'h264') {
      codecFlag = '-c:v libx264';
    } else {
      throw new Error('Unsupported codec. Supported codecs are "av1" and "h264".');
    }

    // Run FFmpeg command to compress video
    await exec(`-i ${inputPath} -c:a copy ${codecFlag} ${outputPath}`);
    console.log('Video compression successful!');
  } catch (error) {
    console.error('Error compressing video:', error);
  }
}

// Example usage
const inputPath = 'path/to/input/video.mp4';
const av1OutputPath = 'path/to/output/compressed_video_av1.mp4';
const h264OutputPath = 'path/to/output/compressed_video_h264.mp4';

// Check if codec argument is provided
const codecArg = process.argv[2];
if (!codecArg) {
  console.error('Please provide a codec argument. Usage: node compress_video.js <codec>');
  process.exit(1);
}

// Compress video based on the codec argument
if (codecArg === 'av1') {
  compressVideo(inputPath, av1OutputPath, 'av1');
} else if (codecArg === 'h264') {
  compressVideo(inputPath, h264OutputPath, 'h264');
} else {
  console.error('Unsupported codec. Supported codecs are "av1" and "h264".');
}

Usage

To compress a video using AV1 codec:

node compress_video.js av1

To compress a video using H.264 codec:

node compress_video.js h264

Replace inputPath and outputPath in the compressVideo function with your desired input and output file paths.

Codecs

  • AV1 (AOMedia Video 1): AV1 is a royalty-free video codec designed for video transmissions over the internet. It offers high compression efficiency and is supported by major browsers like Chrome and Firefox.

  • H.264 (Advanced Video Coding): H.264 is a widely used video codec for compressing and transmitting video streams over the internet. It provides good compression efficiency and is supported by most devices and browsers.

Dependencies

  • @ffmpeg/ffmpeg: FFmpeg package for Node.js.
  • @ffmpeg/util: FFmpeg utilities for Node.js.

Important weblinks


@DHANRAJCHOUDHARY244
Copy link
Author

using sharp and speedtest-net for optimization and serve

@DHANRAJCHOUDHARY244
Copy link
Author

add ffmpeg.wasm for video compressing using latest and very efficient technology using code av1 and h.264 which used by microsoft meta and many more giant companies for streaming videos real time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment