Remplace ta caméra par une image personnalisée sur OmeTV, Omegle et sites similaires
// ==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();
}
})();