Fake Camera - Ommogle

Remplace ta caméra par une image personnalisée sur OmeTV, Omegle et sites similaires

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Fake Camera - Ommogle
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Remplace ta caméra par une image personnalisée sur OmeTV, Omegle et sites similaires
// @author       Claude
// @match        *://*.ommogle.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
  'use strict';

  // ─── CONFIG ───────────────────────────────────────────────
  const CONFIG = {
    imageUrl: null,       // URL de ton image (rempli automatiquement via le panneau)
    fps: 30,
    width: 640,
    height: 480,
  };
  // ──────────────────────────────────────────────────────────

  let fakeStream = null;
  let canvas = null;
  let ctx = null;
  let img = null;
  let animFrame = null;

  // Crée le canvas caché qui sert de fausse caméra
  function createFakeStream(imageUrl) {
    if (fakeStream) {
      fakeStream.getTracks().forEach(t => t.stop());
    }
    if (animFrame) cancelAnimationFrame(animFrame);

    canvas = document.createElement('canvas');
    canvas.width = CONFIG.width;
    canvas.height = CONFIG.height;
    ctx = canvas.getContext('2d');

    img = new Image();
    img.crossOrigin = 'anonymous';

    img.onload = () => {
      const draw = () => {
        ctx.drawImage(img, 0, 0, CONFIG.width, CONFIG.height);
        animFrame = setTimeout(() => requestAnimationFrame(draw), 1000 / CONFIG.fps);
      };
      draw();
    };

    img.onerror = () => {
      // Si l'image échoue, dessine un écran noir avec texte
      ctx.fillStyle = '#000';
      ctx.fillRect(0, 0, CONFIG.width, CONFIG.height);
      ctx.fillStyle = '#fff';
      ctx.font = '20px sans-serif';
      ctx.textAlign = 'center';
      ctx.fillText('Image non chargée', CONFIG.width / 2, CONFIG.height / 2);
    };

    img.src = imageUrl;
    fakeStream = canvas.captureStream(CONFIG.fps);
    return fakeStream;
  }

  // Override getUserMedia pour retourner le faux flux
  const originalGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);

  navigator.mediaDevices.getUserMedia = async function (constraints) {
    // Si la caméra n'est pas demandée, on laisse passer normalement
    if (!constraints || !constraints.video) {
      return originalGetUserMedia(constraints);
    }

    // Si aucune image choisie, on laisse passer la vraie caméra
    if (!CONFIG.imageUrl) {
      console.warn('[FakeCam] Aucune image choisie, utilisation de la vraie caméra.');
      return originalGetUserMedia(constraints);
    }

    console.log('[FakeCam] Flux caméra remplacé par image personnalisée.');
    return createFakeStream(CONFIG.imageUrl);
  };

  // ─── UI PANNEAU ───────────────────────────────────────────
  function createPanel() {
    const panel = document.createElement('div');
    panel.id = 'fakecam-panel';
    panel.innerHTML = `
      <div id="fakecam-header">📷 Fake Camera</div>
      <div id="fakecam-body">
        <label>Colle une URL d'image :</label>
        <input type="text" id="fakecam-url" placeholder="https://..." />
        <label>Ou upload une image :</label>
        <input type="file" id="fakecam-file" accept="image/*" />
        <div id="fakecam-preview-wrap">
          <img id="fakecam-preview" />
        </div>
        <button id="fakecam-apply">✅ Appliquer</button>
        <button id="fakecam-reset">🔄 Désactiver (vraie caméra)</button>
        <div id="fakecam-status">En attente d'une image...</div>
      </div>
    `;

    const style = document.createElement('style');
    style.textContent = `
      #fakecam-panel {
        position: fixed;
        top: 16px;
        right: 16px;
        z-index: 999999;
        background: #1a1a2e;
        color: #eee;
        font-family: monospace;
        font-size: 13px;
        border: 1px solid #444;
        border-radius: 12px;
        width: 260px;
        box-shadow: 0 8px 32px rgba(0,0,0,0.6);
        overflow: hidden;
        transition: all 0.3s ease;
      }
      #fakecam-header {
        background: #16213e;
        padding: 10px 14px;
        font-weight: bold;
        font-size: 14px;
        cursor: pointer;
        user-select: none;
        border-bottom: 1px solid #333;
        letter-spacing: 1px;
      }
      #fakecam-body {
        padding: 12px;
        display: flex;
        flex-direction: column;
        gap: 8px;
      }
      #fakecam-body label {
        font-size: 11px;
        color: #aaa;
        margin-bottom: 2px;
      }
      #fakecam-url {
        background: #0f3460;
        border: 1px solid #555;
        color: #fff;
        border-radius: 6px;
        padding: 6px 8px;
        font-size: 12px;
        width: 100%;
        box-sizing: border-box;
      }
      #fakecam-file {
        font-size: 11px;
        color: #ccc;
      }
      #fakecam-preview-wrap {
        display: flex;
        justify-content: center;
      }
      #fakecam-preview {
        max-width: 100%;
        max-height: 100px;
        border-radius: 6px;
        border: 1px solid #555;
        display: none;
        object-fit: cover;
      }
      #fakecam-apply, #fakecam-reset {
        border: none;
        border-radius: 6px;
        padding: 8px;
        cursor: pointer;
        font-size: 12px;
        font-family: monospace;
        width: 100%;
      }
      #fakecam-apply {
        background: #0f9b58;
        color: #fff;
      }
      #fakecam-apply:hover { background: #0d7a46; }
      #fakecam-reset {
        background: #444;
        color: #ccc;
      }
      #fakecam-reset:hover { background: #333; }
      #fakecam-status {
        font-size: 11px;
        color: #f0a500;
        text-align: center;
        padding: 4px;
      }
    `;

    document.head.appendChild(style);
    document.body.appendChild(panel);

    // Toggle panel
    document.getElementById('fakecam-header').onclick = () => {
      const body = document.getElementById('fakecam-body');
      body.style.display = body.style.display === 'none' ? 'flex' : 'none';
    };

    // Upload fichier → convertir en base64
    document.getElementById('fakecam-file').onchange = function () {
      const file = this.files[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = (e) => {
        document.getElementById('fakecam-url').value = e.target.result;
        showPreview(e.target.result);
      };
      reader.readAsDataURL(file);
    };

    // Aperçu depuis URL
    document.getElementById('fakecam-url').oninput = function () {
      if (this.value) showPreview(this.value);
    };

    function showPreview(src) {
      const preview = document.getElementById('fakecam-preview');
      preview.src = src;
      preview.style.display = 'block';
    }

    // Appliquer
    document.getElementById('fakecam-apply').onclick = () => {
      const url = document.getElementById('fakecam-url').value.trim();
      if (!url) {
        setStatus('❌ Aucune image fournie !', '#e74c3c');
        return;
      }
      CONFIG.imageUrl = url;
      createFakeStream(url);
      setStatus('✅ Image activée ! Relance la caméra sur le site.', '#0f9b58');
    };

    // Reset
    document.getElementById('fakecam-reset').onclick = () => {
      CONFIG.imageUrl = null;
      if (fakeStream) fakeStream.getTracks().forEach(t => t.stop());
      fakeStream = null;
      if (animFrame) cancelAnimationFrame(animFrame);
      setStatus('🔄 Vraie caméra réactivée.', '#aaa');
    };

    function setStatus(msg, color) {
      const s = document.getElementById('fakecam-status');
      s.textContent = msg;
      s.style.color = color || '#f0a500';
    }
  }

  // Attendre que le DOM soit prêt
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', createPanel);
  } else {
    createPanel();
  }

})();