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();
  }

})();