Screenshot Public

HTML Actualizado Aug 23, 2025

Archivos de Código

Screenshot.html

Código principal 584 líneas
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Akiomae Pro Screen Recorder</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: #ffffff;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }

        .container {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            text-align: center;
            max-width: 600px;
            width: 100%;
        }

        h1 {
            font-size: 2.5em;
            margin-bottom: 30px;
            background: linear-gradient(45deg, #fff, #f0f0f0);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }

        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            justify-content: center;
            margin-bottom: 30px;
        }

        button {
            background: rgba(255, 255, 255, 0.2);
            color: #ffffff;
            border: 2px solid rgba(255, 255, 255, 0.3);
            padding: 12px 24px;
            font-size: 1em;
            cursor: pointer;
            transition: all 0.3s ease;
            border-radius: 50px;
            font-weight: 600;
            min-width: 140px;
        }

        button:hover:not(:disabled) {
            background: rgba(255, 255, 255, 0.3);
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }

        button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
        }

        button.recording {
            background: #ff4757;
            border-color: #ff4757;
            animation: pulse 2s infinite;
        }

        button.paused {
            background: #ffa502;
            border-color: #ffa502;
        }

        @keyframes pulse {
            0% { box-shadow: 0 0 0 0 rgba(255, 71, 87, 0.7); }
            70% { box-shadow: 0 0 0 10px rgba(255, 71, 87, 0); }
            100% { box-shadow: 0 0 0 0 rgba(255, 71, 87, 0); }
        }

        .status {
            margin: 20px 0;
            font-size: 1.1em;
            font-weight: 500;
        }

        .timer {
            font-size: 1.5em;
            font-weight: bold;
            color: #ff4757;
            margin: 10px 0;
        }

        video {
            margin-top: 20px;
            width: 100%;
            max-width: 500px;
            border-radius: 15px;
            box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
        }

        .floating-preview {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 200px;
            height: 150px;
            background: rgba(0, 0, 0, 0.8);
            border-radius: 10px;
            overflow: hidden;
            display: none;
            z-index: 1000;
            border: 2px solid #667eea;
        }

        .floating-preview video {
            width: 100%;
            height: 100%;
            object-fit: cover;
            margin: 0;
            border-radius: 0;
            box-shadow: none;
        }

        /* Modal de Exportación */
        .modal {
            display: none;
            position: fixed;
            z-index: 2000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            backdrop-filter: blur(5px);
        }

        .modal-content {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 5% auto;
            padding: 30px;
            border-radius: 20px;
            width: 90%;
            max-width: 500px;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
            text-align: center;
        }

        .modal h2 {
            margin-bottom: 25px;
            font-size: 1.8em;
        }

        .form-group {
            margin-bottom: 20px;
            text-align: left;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
        }

        .form-group input,
        .form-group select {
            width: 100%;
            padding: 12px;
            border: none;
            border-radius: 10px;
            background: rgba(255, 255, 255, 0.2);
            color: #fff;
            font-size: 1em;
        }

        .form-group input::placeholder {
            color: rgba(255, 255, 255, 0.7);
        }

        .modal-buttons {
            display: flex;
            gap: 15px;
            justify-content: center;
            margin-top: 25px;
        }

        .btn-primary {
            background: #2ed573;
            border-color: #2ed573;
        }

        .btn-secondary {
            background: #ff4757;
            border-color: #ff4757;
        }

        .download-info {
            margin-top: 15px;
            padding: 15px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 10px;
            font-size: 0.9em;
        }

        @media (max-width: 768px) {
            .container {
                padding: 20px;
            }
            
            h1 {
                font-size: 2em;
            }
            
            .controls {
                flex-direction: column;
                align-items: center;
            }
            
            button {
                width: 100%;
                max-width: 250px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎥 Akiomae Pro Recorder</h1>
        
        <div class="status" id="status">Listo para grabar</div>
        <div class="timer" id="timer" style="display: none;">00:00:00</div>
        
        <div class="controls">
            <button id="startBtn">🔴 Iniciar Grabación</button>
            <button id="pauseBtn" disabled>⏸️ Pausar</button>
            <button id="stopBtn" disabled>⏹️ Detener</button>
            <button id="muteMicBtn" disabled>🎤 Micrófono</button>
            <button id="muteSystemBtn" disabled>🔊 Audio Sistema</button>
        </div>
        
        <video id="recordedVideo" controls style="display:none;"></video>
    </div>

    <div class="floating-preview" id="floatingPreview">
        <video id="previewVideo" autoplay muted></video>
    </div>

    <!-- Modal de Exportación -->
    <div id="exportModal" class="modal">
        <div class="modal-content">
            <h2>📁 Exportar Grabación</h2>
            
            <div class="form-group">
                <label for="fileName">Nombre del archivo:</label>
                <input type="text" id="fileName" placeholder="Mi_Grabacion_2024">
            </div>
            
            <div class="form-group">
                <label for="fileFormat">Formato de exportación:</label>
                <select id="fileFormat">
                    <option value="webm">WebM (Recomendado)</option>
                    <option value="mp4">MP4 (Compatible)</option>
                    <option value="avi">AVI (Alta calidad)</option>
                </select>
            </div>
            
            <div class="form-group">
                <label for="videoQuality">Calidad del video:</label>
                <select id="videoQuality">
                    <option value="high">Alta (Original)</option>
                    <option value="medium">Media (Comprimido)</option>
                    <option value="low">Baja (Archivo pequeño)</option>
                </select>
            </div>
            
            <div class="download-info">
                <strong>Información:</strong><br>
                Duración: <span id="videoDuration">--</span><br>
                Tamaño estimado: <span id="fileSize">--</span>
            </div>
            
            <div class="modal-buttons">
                <button class="btn-primary" id="downloadBtn">⬇️ Descargar</button>
                <button class="btn-secondary" id="cancelBtn">❌ Cancelar</button>
            </div>
        </div>
    </div>

    <script>
        class ScreenRecorder {
            constructor() {
                this.mediaRecorder = null;
                this.recordedChunks = [];
                this.isRecording = false;
                this.isPaused = false;
                this.startTime = null;
                this.pausedTime = 0;
                this.timerInterval = null;
                this.screenStream = null;
                this.audioStream = null;
                this.combinedStream = null;
                this.recordedBlob = null;
                
                this.initializeElements();
                this.bindEvents();
            }
            
            initializeElements() {
                this.startBtn = document.getElementById('startBtn');
                this.pauseBtn = document.getElementById('pauseBtn');
                this.stopBtn = document.getElementById('stopBtn');
                this.muteMicBtn = document.getElementById('muteMicBtn');
                this.muteSystemBtn = document.getElementById('muteSystemBtn');
                this.recordedVideo = document.getElementById('recordedVideo');
                this.floatingPreview = document.getElementById('floatingPreview');
                this.previewVideo = document.getElementById('previewVideo');
                this.status = document.getElementById('status');
                this.timer = document.getElementById('timer');
                this.exportModal = document.getElementById('exportModal');
                this.fileName = document.getElementById('fileName');
                this.fileFormat = document.getElementById('fileFormat');
                this.videoQuality = document.getElementById('videoQuality');
                this.downloadBtn = document.getElementById('downloadBtn');
                this.cancelBtn = document.getElementById('cancelBtn');
                this.videoDuration = document.getElementById('videoDuration');
                this.fileSize = document.getElementById('fileSize');
            }
            
            bindEvents() {
                this.startBtn.addEventListener('click', () => this.startRecording());
                this.pauseBtn.addEventListener('click', () => this.togglePause());
                this.stopBtn.addEventListener('click', () => this.stopRecording());
                this.muteMicBtn.addEventListener('click', () => this.toggleMicrophone());
                this.muteSystemBtn.addEventListener('click', () => this.toggleSystemAudio());
                this.downloadBtn.addEventListener('click', () => this.downloadVideo());
                this.cancelBtn.addEventListener('click', () => this.closeModal());
            }
            
            async startRecording() {
                try {
                    // Obtener stream de pantalla
                    this.screenStream = await navigator.mediaDevices.getDisplayMedia({
                        video: { mediaSource: 'screen' },
                        audio: true
                    });
                    
                    // Obtener stream de micrófono
                    try {
                        this.audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
                    } catch (e) {
                        console.log('No se pudo acceder al micrófono:', e);
                    }
                    
                    // Combinar streams
                    const tracks = [...this.screenStream.getTracks()];
                    if (this.audioStream) {
                        tracks.push(...this.audioStream.getTracks());
                    }
                    
                    this.combinedStream = new MediaStream(tracks);
                    
                    // Configurar MediaRecorder
                    this.mediaRecorder = new MediaRecorder(this.combinedStream, {
                        mimeType: 'video/webm;codecs=vp9'
                    });
                    
                    this.mediaRecorder.ondataavailable = (event) => {
                        if (event.data.size > 0) {
                            this.recordedChunks.push(event.data);
                        }
                    };
                    
                    this.mediaRecorder.onstop = () => {
                        this.handleRecordingStop();
                    };
                    
                    // Manejar cuando el usuario detiene el compartir pantalla
                    this.screenStream.getVideoTracks()[0].onended = () => {
                        this.stopRecording();
                    };
                    
                    // Iniciar grabación
                    this.mediaRecorder.start(1000); // Guardar chunks cada segundo
                    this.isRecording = true;
                    this.startTime = Date.now();
                    this.startTimer();
                    
                    // Mostrar preview flotante
                    this.previewVideo.srcObject = this.screenStream;
                    this.floatingPreview.style.display = 'block';
                    
                    // Actualizar UI
                    this.updateUI();
                    this.status.textContent = '🔴 Grabando...';
                    
                } catch (error) {
                    console.error('Error al iniciar grabación:', error);
                    alert('Error al acceder a la pantalla. Por favor, permite el acceso.');
                }
            }
            
            togglePause() {
                if (!this.mediaRecorder) return;
                
                if (this.isPaused) {
                    this.mediaRecorder.resume();
                    this.isPaused = false;
                    this.pauseBtn.textContent = '⏸️ Pausar';
                    this.pauseBtn.classList.remove('paused');
                    this.status.textContent = '🔴 Grabando...';
                    this.startTimer();
                } else {
                    this.mediaRecorder.pause();
                    this.isPaused = true;
                    this.pauseBtn.textContent = '▶️ Reanudar';
                    this.pauseBtn.classList.add('paused');
                    this.status.textContent = '⏸️ Pausado';
                    this.stopTimer();
                }
            }
            
            stopRecording() {
                if (this.mediaRecorder && this.isRecording) {
                    this.mediaRecorder.stop();
                    this.isRecording = false;
                    this.isPaused = false;
                    
                    // Detener streams
                    if (this.screenStream) {
                        this.screenStream.getTracks().forEach(track => track.stop());
                    }
                    if (this.audioStream) {
                        this.audioStream.getTracks().forEach(track => track.stop());
                    }
                    
                    this.stopTimer();
                    this.floatingPreview.style.display = 'none';
                    this.status.textContent = '⏹️ Procesando grabación...';
                }
            }
            
            handleRecordingStop() {
                // Crear blob del video grabado
                this.recordedBlob = new Blob(this.recordedChunks, { type: 'video/webm' });
                this.recordedChunks = [];
                
                // Mostrar video grabado
                const videoURL = URL.createObjectURL(this.recordedBlob);
                this.recordedVideo.src = videoURL;
                this.recordedVideo.style.display = 'block';
                
                // Calcular duración y tamaño
                this.recordedVideo.onloadedmetadata = () => {
                    const duration = this.formatTime(this.recordedVideo.duration);
                    const size = this.formatFileSize(this.recordedBlob.size);
                    
                    this.videoDuration.textContent = duration;
                    this.fileSize.textContent = size;
                };
                
                // Generar nombre por defecto
                const now = new Date();
                const defaultName = `Grabacion_${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2,'0')}-${now.getDate().toString().padStart(2,'0')}_${now.getHours().toString().padStart(2,'0')}-${now.getMinutes().toString().padStart(2,'0')}`;
                this.fileName.value = defaultName;
                
                // Mostrar modal de exportación
                this.exportModal.style.display = 'block';
                
                // Resetear UI
                this.updateUI();
                this.status.textContent = '✅ Grabación completada';
            }
            
            toggleMicrophone() {
                if (this.audioStream) {
                    const audioTrack = this.audioStream.getAudioTracks()[0];
                    audioTrack.enabled = !audioTrack.enabled;
                    this.muteMicBtn.textContent = audioTrack.enabled ? '🎤 Micrófono' : '🎤 Muted';
                }
            }
            
            toggleSystemAudio() {
                if (this.screenStream) {
                    const audioTracks = this.screenStream.getAudioTracks();
                    if (audioTracks.length > 0) {
                        audioTracks[0].enabled = !audioTracks[0].enabled;
                        this.muteSystemBtn.textContent = audioTracks[0].enabled ? '🔊 Audio Sistema' : '🔊 Muted';
                    }
                }
            }
            
            downloadVideo() {
                if (!this.recordedBlob) return;
                
                const fileName = this.fileName.value || 'grabacion';
                const format = this.fileFormat.value;
                
                // Crear enlace de descarga
                const url = URL.createObjectURL(this.recordedBlob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `${fileName}.${format}`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
                
                this.closeModal();
                this.status.textContent = '⬇️ Descarga iniciada';
            }
            
            closeModal() {
                this.exportModal.style.display = 'none';
            }
            
            startTimer() {
                this.timer.style.display = 'block';
                this.timerInterval = setInterval(() => {
                    const elapsed = Date.now() - this.startTime - this.pausedTime;
                    this.timer.textContent = this.formatTime(elapsed / 1000);
                }, 1000);
            }
            
            stopTimer() {
                if (this.timerInterval) {
                    clearInterval(this.timerInterval);
                    this.timerInterval = null;
                }
            }
            
            formatTime(seconds) {
                const hrs = Math.floor(seconds / 3600);
                const mins = Math.floor((seconds % 3600) / 60);
                const secs = Math.floor(seconds % 60);
                return `${hrs.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
            }
            
            formatFileSize(bytes) {
                if (bytes === 0) return '0 Bytes';
                const k = 1024;
                const sizes = ['Bytes', 'KB', 'MB', 'GB'];
                const i = Math.floor(Math.log(bytes) / Math.log(k));
                return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
            }
            
            updateUI() {
                this.startBtn.disabled = this.isRecording;
                this.pauseBtn.disabled = !this.isRecording;
                this.stopBtn.disabled = !this.isRecording;
                this.muteMicBtn.disabled = !this.isRecording;
                this.muteSystemBtn.disabled = !this.isRecording;
                
                if (this.isRecording) {
                    this.startBtn.classList.add('recording');
                } else {
                    this.startBtn.classList.remove('recording');
                    this.pauseBtn.classList.remove('paused');
                    this.timer.style.display = 'none';
                }
            }
        }
        
        // Inicializar la aplicación
        document.addEventListener('DOMContentLoaded', () => {
            new ScreenRecorder();
        });
    </script>
</body>
</html>

Comentarios (0)

¡Aún no hay comentarios. Sé el primero en comentar!