Skip to content

Ros245/userscripts

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

// ==UserScript== // @name Virtual Webcam Mix // @namespace http://tampermonkey.net/ // @version 1.7 // @description Exibe imagem ou vídeo como webcam virtual // @author Seu Nome // @match https://idnvui.vfsglobal.com/* // @grant GM_addStyle // @grant window.onurlchange // @require https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js // ==/UserScript==

(function() { 'use strict';

let virtualStream = null;
let mediaSource = null;
let canvasContext = null;
let mediaElement = null;

// Interface do usuário
GM_addStyle(`
    #virtualCamUI {
        position: fixed;
        top: 20px;
        right: 20px;
        background: rgba(0,0,0,0.95);
        padding: 15px;
        border-radius: 10px;
        z-index: 999999;
        color: white;
        font-family: Arial, sans-serif;
        width: 300px;
        box-shadow: 0 0 15px rgba(0,0,0,0.7);
    }

    .vcam-btn {
        background: #2196F3;
        border: none;
        color: white;
        padding: 10px;
        margin: 5px 0;
        border-radius: 5px;
        cursor: pointer;
        width: 100%;
        transition: transform 0.2s;
    }

    .vcam-btn:hover {
        transform: scale(1.05);
    }

    #mediaPreview {
        max-width: 100%;
        margin: 10px 0;
        border-radius: 5px;
        display: none;
    }

    #status {
        font-size: 12px;
        text-align: center;
        margin-top: 10px;
        color: #00ff00;
    }
`);

const ui = document.createElement('div');
ui.id = 'virtualCamUI';
ui.innerHTML = `
    <input type="file" id="mediaInput" accept="video/*,image/*" hidden>
    <button class="vcam-btn" id="loadMedia">📁 Carregar Mídia</button>
    <button class="vcam-btn" id="toggleCam" disabled>🎥 Iniciar Webcam Virtual</button>
    <div id="previewContainer"></div>
    <div id="status">Status: Pronto</div>
    <canvas id="hiddenCanvas" hidden></canvas>
`;

document.body.appendChild(ui);

// Elementos DOM
const previewContainer = document.getElementById('previewContainer');
const loadButton = document.getElementById('loadMedia');
const toggleButton = document.getElementById('toggleCam');
const hiddenCanvas = document.getElementById('hiddenCanvas');

// Configurar canvas
hiddenCanvas.width = 640;
hiddenCanvas.height = 480;
canvasContext = hiddenCanvas.getContext('2d');

// Interceptar webcam
const originalGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);

navigator.mediaDevices.getUserMedia = async (constraints) => {
    if (constraints.video && virtualStream) {
        return virtualStream.clone();
    }
    return originalGetUserMedia(constraints);
};

// Eventos
loadButton.addEventListener('click', () => document.getElementById('mediaInput').click());

document.getElementById('mediaInput').addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    if (mediaSource) URL.revokeObjectURL(mediaSource);

    mediaSource = URL.createObjectURL(file);
    toggleButton.disabled = false;

    // Remover mídia anterior
    if (mediaElement) previewContainer.removeChild(mediaElement);

    if (file.type.startsWith('video/')) {
        // Criar vídeo
        mediaElement = document.createElement('video');
        mediaElement.src = mediaSource;
        mediaElement.controls = true;
        mediaElement.loop = true;
        mediaElement.muted = true;
        mediaElement.playsInline = true;
        mediaElement.style.maxWidth = '100%';
    } else {
        // Criar imagem
        mediaElement = document.createElement('img');
        mediaElement.src = mediaSource;
        mediaElement.style.maxWidth = '100%';
    }

    previewContainer.appendChild(mediaElement);
    updateStatus('Mídia carregada com sucesso!');
});

toggleButton.addEventListener('click', () => {
    if (virtualStream) {
        stopVirtualCam();
        toggleButton.textContent = '🎥 Iniciar Webcam Virtual';
    } else {
        startVirtualCam();
        toggleButton.textContent = '⏹ Parar Webcam Virtual';
    }
});

// Funções principais
function startVirtualCam() {
    if (!mediaSource || !mediaElement) {
        updateStatus('Carregue uma mídia primeiro!', true);
        return;
    }

    if (mediaElement.tagName === 'IMG') {
        handleImageSource();
    } else if (mediaElement.tagName === 'VIDEO') {
        handleVideoSource();
    }
}

function handleImageSource() {
    const img = new Image();
    img.onload = () => {
        hiddenCanvas.width = img.naturalWidth;
        hiddenCanvas.height = img.naturalHeight;

        const drawFrame = () => {
            canvasContext.drawImage(img, 0, 0, hiddenCanvas.width, hiddenCanvas.height);
            requestAnimationFrame(drawFrame);
        };

        drawFrame();

        const stream = hiddenCanvas.captureStream(30);
        virtualStream = new MediaStream([stream.getVideoTracks()[0]]);
        updateStatus('Imagem sendo transmitida como vídeo!');
    };
    img.src = mediaSource;
}

function handleVideoSource() {
    mediaElement.play().then(() => {
        const stream = mediaElement.captureStream(30);
        virtualStream = new MediaStream([stream.getVideoTracks()[0]]);
        updateStatus('Vídeo sendo transmitido!');
    }).catch(error => {
        updateStatus(`Erro: ${error.message}`, true);
    });
}

function stopVirtualCam() {
    if (virtualStream) {
        virtualStream.getTracks().forEach(track => track.stop());
        virtualStream = null;
    }
    updateStatus('Webcam real restaurada');
}

function updateStatus(message, isError = false) {
    const status = document.getElementById('status');
    status.textContent = `Status: ${message}`;
    status.style.color = isError ? '#ff0000' : '#00ff00';
}

// Limpeza
window.addEventListener('beforeunload', () => {
    if (virtualStream) virtualStream.getTracks().forEach(track => track.stop());
    if (mediaSource) URL.revokeObjectURL(mediaSource);
});

})();

About

An open-source userscript manager for Safari

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 35.4%
  • JavaScript 32.3%
  • Svelte 28.1%
  • CSS 3.2%
  • Other 1.0%