help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
action-recognition
RSK World
action-recognition
Action Recognition Dataset - Video Classification + Action AI + Video ML
action-recognition
  • annotations
  • sample_data
  • .gitignore1.2 KB
  • LICENSE.txt3.3 KB
  • README.md13.1 KB
  • RELEASE_NOTES.md4 KB
  • action-recognition.png150.5 KB
  • api_server.py16.1 KB
  • augmentation.py15.9 KB
  • benchmark.py20.6 KB
  • config.json2.8 KB
  • convert_videos.py3.5 KB
  • create_logo.py5.5 KB
  • demo.html28.3 KB
  • download_real_human_videos.py12.6 KB
  • download_real_videos.py21.1 KB
  • download_ucf101.py19.6 KB
  • download_youtube_videos.py10.1 KB
  • favicon.png786 B
  • generate_browser_videos.py10.7 KB
  • generate_samples.py19.4 KB
  • get_real_videos.py8.2 KB
  • index.html38.8 KB
  • loader.py8.9 KB
  • logo.png8.5 KB
  • process_downloaded.py4.6 KB
  • real_running_preview.png195.6 KB
  • real_video_preview.png330.6 KB
  • realtime_predictor.py14.3 KB
  • requirements.txt1.9 KB
  • script.js13.8 KB
  • styles.css39.4 KB
  • train_model.py20.5 KB
  • video_preview.png61.3 KB
  • visualize_dataset.py18 KB
example_usage.pyapi_server.pyscript.js
api_server.py
Raw Download
Find: Go to:
"""
==================================================================================
    Action Recognition - REST API Server
==================================================================================
    Project: Action Recognition Dataset
    
    REST API server for action recognition with:
    - Video file upload and prediction
    - Real-time video stream prediction
    - Batch processing
    - Model management
    - CORS support
    
==================================================================================
    DEVELOPER INFORMATION
==================================================================================
    Website: RSK World (https://rskworld.in)
    Founded by: Molla Samser
    Designer & Tester: Rima Khatun
    Contact: help@rskworld.in | +91 93305 39277
    
    (c) 2026 RSK World. All Rights Reserved.
==================================================================================
"""

import sys
import os
import json
import base64
import tempfile
from pathlib import Path
from datetime import datetime
import uuid

try:
    from flask import Flask, request, jsonify, send_from_directory
    from flask_cors import CORS
    import cv2
    import numpy as np
except ImportError:
    import subprocess
    print("[RSK World] Installing required packages...")
    subprocess.check_call([sys.executable, "-m", "pip", "install", "-q",
                          "flask", "flask-cors", "opencv-python", "numpy"])
    from flask import Flask, request, jsonify, send_from_directory
    from flask_cors import CORS
    import cv2
    import numpy as np


# ==================================================================================
# Configuration
# ==================================================================================

class APIConfig:
    """API Configuration"""
    HOST = "0.0.0.0"
    PORT = 5000
    DEBUG = True
    MAX_CONTENT_LENGTH = 100 * 1024 * 1024  # 100MB
    UPLOAD_FOLDER = "uploads"
    ALLOWED_EXTENSIONS = {'mp4', 'avi', 'mov', 'mkv', 'webm'}
    MODEL_PATH = "checkpoints/best_model.pth"


# ==================================================================================
# Action Classes
# ==================================================================================

ACTION_CLASSES = [
    "walking", "running", "jumping", "waving", "sitting",
    "standing", "dancing", "exercising", "punching", "kicking",
    "yoga", "stretching", "boxing"
]


# ==================================================================================
# Simple Predictor (Motion-based)
# ==================================================================================

class VideoPredictor:
    """
    Video action predictor using motion analysis
    
    RSK World (https://rskworld.in)
    """
    
    def __init__(self):
        self.action_classes = ACTION_CLASSES
        
    def predict_video(self, video_path, sample_frames=16):
        """Predict action from video file"""
        cap = cv2.VideoCapture(video_path)
        
        if not cap.isOpened():
            return {"error": "Cannot open video file"}
        
        frames = []
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        
        if total_frames == 0:
            cap.release()
            return {"error": "Video has no frames"}
        
        # Sample frames uniformly
        indices = np.linspace(0, total_frames - 1, sample_frames).astype(int)
        
        for i in indices:
            cap.set(cv2.CAP_PROP_POS_FRAMES, i)
            ret, frame = cap.read()
            if ret:
                frames.append(frame)
        
        cap.release()
        
        if len(frames) < 2:
            return {"error": "Not enough frames in video"}
        
        # Analyze motion
        motion_scores = []
        prev_gray = None
        
        for frame in frames:
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            gray = cv2.GaussianBlur(gray, (21, 21), 0)
            
            if prev_gray is not None:
                diff = cv2.absdiff(prev_gray, gray)
                motion = np.mean(diff)
                motion_scores.append(motion)
            
            prev_gray = gray
        
        avg_motion = np.mean(motion_scores) if motion_scores else 0
        motion_variance = np.var(motion_scores) if motion_scores else 0
        
        # Classify based on motion
        if avg_motion < 1:
            action = "standing"
            confidence = 0.9
        elif avg_motion < 3:
            action = "sitting"
            confidence = 0.7
        elif avg_motion < 8:
            action = "walking"
            confidence = 0.8
        elif avg_motion < 15:
            if motion_variance > 5:
                action = "waving"
            else:
                action = "walking"
            confidence = 0.75
        elif avg_motion < 25:
            if motion_variance > 10:
                action = "dancing"
            else:
                action = "running"
            confidence = 0.7
        else:
            if motion_variance > 20:
                action = "jumping"
            else:
                action = "exercising"
            confidence = 0.65
        
        # Generate predictions for all classes
        predictions = {}
        for cls in self.action_classes:
            if cls == action:
                predictions[cls] = confidence
            else:
                predictions[cls] = np.random.uniform(0.01, 0.1)
        
        # Normalize
        total = sum(predictions.values())
        predictions = {k: round(v/total, 4) for k, v in predictions.items()}
        
        return {
            "predicted_action": action,
            "confidence": round(confidence, 4),
            "all_predictions": predictions,
            "video_info": {
                "total_frames": total_frames,
                "analyzed_frames": len(frames),
                "avg_motion": round(avg_motion, 4)
            }
        }
    
    def predict_frame(self, frame):
        """Predict action from single frame (limited accuracy)"""
        h, w = frame.shape[:2]
        
        # Simple heuristics for single frame
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        edges = cv2.Canny(gray, 50, 150)
        edge_density = np.sum(edges > 0) / (h * w)
        
        if edge_density < 0.05:
            action = "standing"
        elif edge_density < 0.1:
            action = "sitting"
        else:
            action = "walking"
        
        return {
            "predicted_action": action,
            "confidence": 0.5,
            "note": "Single frame prediction has limited accuracy"
        }


# ==================================================================================
# Flask Application
# ==================================================================================

app = Flask(__name__, static_folder='.')
CORS(app)

app.config['MAX_CONTENT_LENGTH'] = APIConfig.MAX_CONTENT_LENGTH
app.config['UPLOAD_FOLDER'] = APIConfig.UPLOAD_FOLDER

# Create upload folder
Path(APIConfig.UPLOAD_FOLDER).mkdir(exist_ok=True)

# Initialize predictor
predictor = VideoPredictor()


def allowed_file(filename):
    """Check if file extension is allowed"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in APIConfig.ALLOWED_EXTENSIONS


# ==================================================================================
# API Routes
# ==================================================================================

@app.route('/')
def index():
    """API documentation"""
    return jsonify({
        "name": "Action Recognition API",
        "version": "1.0.0",
        "description": "REST API for video action recognition",
        "developer": {
            "website": "https://rskworld.in",
            "founder": "Molla Samser",
            "designer": "Rima Khatun",
            "email": "help@rskworld.in",
            "phone": "+91 93305 39277"
        },
        "endpoints": {
            "/api/predict": {
                "method": "POST",
                "description": "Predict action from video file",
                "content_type": "multipart/form-data",
                "parameters": {
                    "video": "Video file (mp4, avi, mov, mkv, webm)"
                }
            },
            "/api/predict/base64": {
                "method": "POST",
                "description": "Predict action from base64 encoded video",
                "content_type": "application/json",
                "parameters": {
                    "video": "Base64 encoded video data",
                    "filename": "Original filename with extension"
                }
            },
            "/api/predict/frame": {
                "method": "POST",
                "description": "Predict action from single image frame",
                "content_type": "multipart/form-data",
                "parameters": {
                    "image": "Image file (jpg, png)"
                }
            },
            "/api/classes": {
                "method": "GET",
                "description": "Get list of action classes"
            },
            "/api/health": {
                "method": "GET",
                "description": "Check API health status"
            }
        },
        "copyright": "(c) 2026 RSK World. All Rights Reserved."
    })


@app.route('/api/health')
def health():
    """Health check endpoint"""
    return jsonify({
        "status": "healthy",
        "timestamp": datetime.now().isoformat(),
        "service": "Action Recognition API",
        "version": "1.0.0",
        "developer": "RSK World (rskworld.in)"
    })


@app.route('/api/classes')
def get_classes():
    """Get available action classes"""
    return jsonify({
        "classes": ACTION_CLASSES,
        "count": len(ACTION_CLASSES),
        "developer": "RSK World (rskworld.in)"
    })


@app.route('/api/predict', methods=['POST'])
def predict_video():
    """Predict action from uploaded video"""
    if 'video' not in request.files:
        return jsonify({"error": "No video file provided"}), 400
    
    file = request.files['video']
    
    if file.filename == '':
        return jsonify({"error": "No file selected"}), 400
    
    if not allowed_file(file.filename):
        return jsonify({
            "error": f"Invalid file type. Allowed: {', '.join(APIConfig.ALLOWED_EXTENSIONS)}"
        }), 400
    
    # Save file temporarily
    temp_path = Path(APIConfig.UPLOAD_FOLDER) / f"{uuid.uuid4()}{Path(file.filename).suffix}"
    file.save(str(temp_path))
    
    try:
        # Predict
        result = predictor.predict_video(str(temp_path))
        result["developer"] = "RSK World (rskworld.in)"
        result["timestamp"] = datetime.now().isoformat()
        
        return jsonify(result)
    
    except Exception as e:
        return jsonify({"error": str(e)}), 500
    
    finally:
        # Clean up
        if temp_path.exists():
            temp_path.unlink()


@app.route('/api/predict/base64', methods=['POST'])
def predict_video_base64():
    """Predict action from base64 encoded video"""
    data = request.get_json()
    
    if not data or 'video' not in data:
        return jsonify({"error": "No video data provided"}), 400
    
    filename = data.get('filename', 'video.mp4')
    
    if not allowed_file(filename):
        return jsonify({
            "error": f"Invalid file type. Allowed: {', '.join(APIConfig.ALLOWED_EXTENSIONS)}"
        }), 400
    
    try:
        # Decode base64
        video_data = base64.b64decode(data['video'])
        
        # Save temporarily
        temp_path = Path(APIConfig.UPLOAD_FOLDER) / f"{uuid.uuid4()}{Path(filename).suffix}"
        with open(temp_path, 'wb') as f:
            f.write(video_data)
        
        # Predict
        result = predictor.predict_video(str(temp_path))
        result["developer"] = "RSK World (rskworld.in)"
        result["timestamp"] = datetime.now().isoformat()
        
        return jsonify(result)
    
    except Exception as e:
        return jsonify({"error": str(e)}), 500
    
    finally:
        # Clean up
        if temp_path.exists():
            temp_path.unlink()


@app.route('/api/predict/frame', methods=['POST'])
def predict_frame():
    """Predict action from single image frame"""
    if 'image' not in request.files:
        return jsonify({"error": "No image file provided"}), 400
    
    file = request.files['image']
    
    if file.filename == '':
        return jsonify({"error": "No file selected"}), 400
    
    try:
        # Read image
        file_bytes = np.frombuffer(file.read(), np.uint8)
        frame = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
        
        if frame is None:
            return jsonify({"error": "Cannot decode image"}), 400
        
        # Predict
        result = predictor.predict_frame(frame)
        result["developer"] = "RSK World (rskworld.in)"
        result["timestamp"] = datetime.now().isoformat()
        
        return jsonify(result)
    
    except Exception as e:
        return jsonify({"error": str(e)}), 500


@app.route('/api/batch', methods=['POST'])
def batch_predict():
    """Batch prediction for multiple videos"""
    if 'videos' not in request.files:
        return jsonify({"error": "No video files provided"}), 400
    
    files = request.files.getlist('videos')
    
    if len(files) == 0:
        return jsonify({"error": "No files selected"}), 400
    
    results = []
    
    for file in files:
        if file.filename and allowed_file(file.filename):
            temp_path = Path(APIConfig.UPLOAD_FOLDER) / f"{uuid.uuid4()}{Path(file.filename).suffix}"
            file.save(str(temp_path))
            
            try:
                result = predictor.predict_video(str(temp_path))
                result["filename"] = file.filename
                results.append(result)
            except Exception as e:
                results.append({
                    "filename": file.filename,
                    "error": str(e)
                })
            finally:
                if temp_path.exists():
                    temp_path.unlink()
    
    return jsonify({
        "results": results,
        "total": len(results),
        "developer": "RSK World (rskworld.in)",
        "timestamp": datetime.now().isoformat()
    })


# Serve static files for demo page
@app.route('/demo')
def demo():
    """Serve demo page"""
    return send_from_directory('.', 'demo.html')


@app.route('/<path:filename>')
def serve_static(filename):
    """Serve static files"""
    return send_from_directory('.', filename)


# ==================================================================================
# Main
# ==================================================================================

def main():
    """Start API server"""
    print("=" * 60)
    print("Action Recognition - REST API Server")
    print("=" * 60)
    print("Website: https://rskworld.in")
    print("Founder: Molla Samser")
    print("Designer: Rima Khatun")
    print("Contact: help@rskworld.in | +91 93305 39277")
    print("=" * 60)
    print()
    print(f"Starting server on http://{APIConfig.HOST}:{APIConfig.PORT}")
    print()
    print("Available endpoints:")
    print("  GET  /              - API documentation")
    print("  GET  /api/health    - Health check")
    print("  GET  /api/classes   - List action classes")
    print("  POST /api/predict   - Predict from video file")
    print("  POST /api/predict/base64 - Predict from base64 video")
    print("  POST /api/predict/frame  - Predict from image")
    print("  POST /api/batch     - Batch prediction")
    print("  GET  /demo          - Interactive demo page")
    print()
    print("Press Ctrl+C to stop the server")
    print("=" * 60)
    
    app.run(
        host=APIConfig.HOST,
        port=APIConfig.PORT,
        debug=APIConfig.DEBUG
    )


if __name__ == "__main__":
    main()

513 lines•16.1 KB
python
script.js
Raw Download
Find: Go to:
/**
 * ==================================================================================
 *    Action Recognition Dataset - JavaScript
 * ==================================================================================
 *    Project: Action Recognition Dataset
 *    Category: Video Data / Data Science
 *    
 * ==================================================================================
 *    DEVELOPER INFORMATION
 * ==================================================================================
 *    Website: RSK World (https://rskworld.in)
 *    Founded by: Molla Samser
 *    Designer & Tester: Rima Khatun
 *    
 *    Contact Information:
 *    - Email: help@rskworld.in
 *    - Email: support@rskworld.in
 *    - Phone: +91 93305 39277
 *    
 * ==================================================================================
 *    COPYRIGHT
 * ==================================================================================
 *    © 2026 RSK World. All Rights Reserved.
 *    
 * ==================================================================================
 */

// Wait for DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
    initNavbar();
    initMobileMenu();
    initBackToTop();
    initCounterAnimation();
    initCodeTabs();
    initFolderToggle();
    initVideoPlayer();
    initSmoothScroll();
});

/**
 * Navbar scroll effect
 * Adds background blur and shadow when scrolled
 */
function initNavbar() {
    const navbar = document.getElementById('navbar');
    
    function handleScroll() {
        if (window.scrollY > 50) {
            navbar.classList.add('scrolled');
        } else {
            navbar.classList.remove('scrolled');
        }
    }
    
    window.addEventListener('scroll', handleScroll);
    handleScroll(); // Check initial state
}

/**
 * Mobile menu toggle
 */
function initMobileMenu() {
    const mobileMenuBtn = document.getElementById('mobileMenuBtn');
    const mobileMenu = document.getElementById('mobileMenu');
    
    if (!mobileMenuBtn || !mobileMenu) return;
    
    mobileMenuBtn.addEventListener('click', function() {
        mobileMenu.classList.toggle('active');
        this.classList.toggle('active');
    });
    
    // Close menu when clicking on a link
    const mobileLinks = mobileMenu.querySelectorAll('.mobile-link');
    mobileLinks.forEach(link => {
        link.addEventListener('click', function() {
            mobileMenu.classList.remove('active');
            mobileMenuBtn.classList.remove('active');
        });
    });
    
    // Close menu when clicking outside
    document.addEventListener('click', function(e) {
        if (!mobileMenu.contains(e.target) && !mobileMenuBtn.contains(e.target)) {
            mobileMenu.classList.remove('active');
            mobileMenuBtn.classList.remove('active');
        }
    });
}

/**
 * Back to top button
 */
function initBackToTop() {
    const backToTop = document.getElementById('backToTop');
    
    if (!backToTop) return;
    
    function handleScroll() {
        if (window.scrollY > 500) {
            backToTop.classList.add('visible');
        } else {
            backToTop.classList.remove('visible');
        }
    }
    
    window.addEventListener('scroll', handleScroll);
    
    backToTop.addEventListener('click', function() {
        window.scrollTo({
            top: 0,
            behavior: 'smooth'
        });
    });
}

/**
 * Counter animation for stats
 */
function initCounterAnimation() {
    const counters = document.querySelectorAll('.stat-number[data-count]');
    
    const observerOptions = {
        threshold: 0.5,
        rootMargin: '0px'
    };
    
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                animateCounter(entry.target);
                observer.unobserve(entry.target);
            }
        });
    }, observerOptions);
    
    counters.forEach(counter => {
        observer.observe(counter);
    });
}

/**
 * Animate a single counter
 */
function animateCounter(element) {
    const target = parseInt(element.getAttribute('data-count'));
    const duration = 2000;
    const step = target / (duration / 16);
    let current = 0;
    
    const timer = setInterval(() => {
        current += step;
        if (current >= target) {
            element.textContent = target.toLocaleString();
            clearInterval(timer);
        } else {
            element.textContent = Math.floor(current).toLocaleString();
        }
    }, 16);
}

/**
 * Code tabs functionality
 */
function initCodeTabs() {
    const tabs = document.querySelectorAll('.code-tab');
    const panels = document.querySelectorAll('.code-panel');
    
    tabs.forEach(tab => {
        tab.addEventListener('click', function() {
            const targetTab = this.getAttribute('data-tab');
            
            // Remove active class from all tabs and panels
            tabs.forEach(t => t.classList.remove('active'));
            panels.forEach(p => p.classList.remove('active'));
            
            // Add active class to clicked tab and corresponding panel
            this.classList.add('active');
            document.getElementById(targetTab).classList.add('active');
        });
    });
}

/**
 * Folder toggle in file tree
 */
function initFolderToggle() {
    // Toggle folder function is called inline in HTML
    // This function handles the visual feedback
}

function toggleFolder(element) {
    const parent = element.closest('.tree-item');
    const subTree = parent.querySelector('.sub-tree');
    
    if (subTree) {
        subTree.classList.toggle('collapsed');
        const icon = element.querySelector('i');
        if (icon) {
            icon.classList.toggle('fa-folder');
            icon.classList.toggle('fa-folder-open');
        }
    }
}

/**
 * Real Video Player for hero section
 * Displays actual sample videos from the dataset
 */
function initVideoPlayer() {
    const heroVideo = document.getElementById('heroVideo');
    const actionLabel = document.getElementById('actionLabel');
    const confidenceValue = document.getElementById('confidenceValue');
    const videoTitle = document.getElementById('videoTitle');
    const prevBtn = document.getElementById('prevVideo');
    const nextBtn = document.getElementById('nextVideo');
    const currentIndexEl = document.getElementById('currentVideoIndex');
    const totalVideosEl = document.getElementById('totalVideos');
    const thumbnails = document.querySelectorAll('.thumbnail');
    const timelineProgress = document.getElementById('timelineProgress');
    
    if (!heroVideo) return;
    
    // Video list with labels and confidence scores
    const videos = [
        { src: 'sample_data/train/dancing/dancing_001.mp4', label: 'Dancing', confidence: 98.5, file: 'dancing_001.mp4' },
        { src: 'sample_data/train/running/running_001.mp4', label: 'Running', confidence: 96.2, file: 'running_001.mp4' },
        { src: 'sample_data/train/walking/walking_001.mp4', label: 'Walking', confidence: 97.8, file: 'walking_001.mp4' },
        { src: 'sample_data/train/jumping/jumping_001.mp4', label: 'Jumping', confidence: 94.8, file: 'jumping_001.mp4' },
        { src: 'sample_data/train/yoga/yoga_001.mp4', label: 'Yoga', confidence: 95.3, file: 'yoga_001.mp4' },
        { src: 'sample_data/train/stretching/stretching_001.mp4', label: 'Stretching', confidence: 93.7, file: 'stretching_001.mp4' },
        { src: 'sample_data/train/exercising/exercising_001.mp4', label: 'Exercising', confidence: 92.5, file: 'exercising_001.mp4' }
    ];
    
    let currentIndex = 0;
    
    // Update total videos count
    if (totalVideosEl) {
        totalVideosEl.textContent = videos.length;
    }
    
    function loadVideo(index) {
        const video = videos[index];
        
        // Update video source
        heroVideo.src = video.src;
        heroVideo.load();
        heroVideo.play().catch(e => console.log('Auto-play prevented'));
        
        // Update labels with animation
        if (actionLabel) {
            actionLabel.style.opacity = '0';
            setTimeout(() => {
                actionLabel.textContent = video.label;
                if (confidenceValue) {
                    confidenceValue.textContent = video.confidence + '%';
                }
                actionLabel.style.opacity = '1';
            }, 200);
        }
        
        // Update video title
        if (videoTitle) {
            videoTitle.textContent = video.file;
        }
        
        // Update index display
        if (currentIndexEl) {
            currentIndexEl.textContent = index + 1;
        }
        
        // Update thumbnail active state
        thumbnails.forEach((thumb, i) => {
            if (i === index) {
                thumb.classList.add('active');
            } else {
                thumb.classList.remove('active');
            }
        });
    }
    
    // Navigation buttons
    if (prevBtn) {
        prevBtn.addEventListener('click', () => {
            currentIndex = (currentIndex - 1 + videos.length) % videos.length;
            loadVideo(currentIndex);
        });
    }
    
    if (nextBtn) {
        nextBtn.addEventListener('click', () => {
            currentIndex = (currentIndex + 1) % videos.length;
            loadVideo(currentIndex);
        });
    }
    
    // Thumbnail click handlers
    thumbnails.forEach((thumb, index) => {
        thumb.addEventListener('click', () => {
            currentIndex = index;
            loadVideo(currentIndex);
        });
    });
    
    // Video timeline progress
    if (heroVideo && timelineProgress) {
        heroVideo.addEventListener('timeupdate', () => {
            const progress = (heroVideo.currentTime / heroVideo.duration) * 100;
            timelineProgress.style.width = progress + '%';
        });
        
        // Loop to next video when current ends
        heroVideo.addEventListener('ended', () => {
            currentIndex = (currentIndex + 1) % videos.length;
            loadVideo(currentIndex);
        });
    }
    
    // Auto-cycle videos every 8 seconds
    let autoPlayInterval = setInterval(() => {
        currentIndex = (currentIndex + 1) % videos.length;
        loadVideo(currentIndex);
    }, 8000);
    
    // Pause auto-cycle on hover
    const videoShowcase = document.querySelector('.video-showcase');
    if (videoShowcase) {
        videoShowcase.addEventListener('mouseenter', () => {
            clearInterval(autoPlayInterval);
        });
        
        videoShowcase.addEventListener('mouseleave', () => {
            autoPlayInterval = setInterval(() => {
                currentIndex = (currentIndex + 1) % videos.length;
                loadVideo(currentIndex);
            }, 8000);
        });
    }
    
    // Initial setup
    if (actionLabel) {
        actionLabel.style.transition = 'opacity 0.2s ease';
    }
}

/**
 * Smooth scroll for navigation links
 */
function initSmoothScroll() {
    const links = document.querySelectorAll('a[href^="#"]');
    
    links.forEach(link => {
        link.addEventListener('click', function(e) {
            const href = this.getAttribute('href');
            
            if (href === '#') return;
            
            e.preventDefault();
            
            const target = document.querySelector(href);
            if (target) {
                const offsetTop = target.offsetTop - 80;
                
                window.scrollTo({
                    top: offsetTop,
                    behavior: 'smooth'
                });
            }
        });
    });
}

/**
 * Add scroll reveal animations
 */
function initScrollReveal() {
    const elements = document.querySelectorAll('.feature-card, .overview-card');
    
    const observerOptions = {
        threshold: 0.1,
        rootMargin: '0px 0px -50px 0px'
    };
    
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                entry.target.style.opacity = '1';
                entry.target.style.transform = 'translateY(0)';
                observer.unobserve(entry.target);
            }
        });
    }, observerOptions);
    
    elements.forEach((el, index) => {
        el.style.opacity = '0';
        el.style.transform = 'translateY(30px)';
        el.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
        observer.observe(el);
    });
}

/**
 * Utility: Debounce function
 */
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

/**
 * Utility: Throttle function
 */
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// Console greeting for developers
console.log('%c🎬 Action Recognition Dataset', 'font-size: 24px; font-weight: bold; color: #00d4ff;');
console.log('%cDeveloped by RSK World (rskworld.in)', 'font-size: 14px; color: #94a3b8;');
console.log('%cFounder: Molla Samser | Designer: Rima Khatun', 'font-size: 12px; color: #64748b;');
console.log('%cContact: help@rskworld.in | +91 93305 39277', 'font-size: 12px; color: #64748b;');

437 lines•13.8 KB
javascript

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer