Google Meet Recorder

Records Google Meet meetings including video

Size

6.3 KB

Version

0.0.1

Created

Mar 30, 2026

Updated

17 days ago

1// ==UserScript==
2// @name		Google Meet Recorder
3// @description		Records Google Meet meetings including video
4// @author		Robomonkey
5// @match		https://meet.google.com/*
6// @grant		none
7// @version		0.0.1
8// ==/UserScript==
9(function() {
10    'use strict';
11
12    let recording = false;
13    let mediaRecorder;
14    let recordedChunks = [];
15
16    function init() {
17        console.log('Google Meet Recorder: Initializing...');
18        // Simplified detection - just check if we're on a Google Meet page
19        if (window.location.hostname.includes('meet.google.com')) {
20            console.log('Google Meet Recorder: On Google Meet page');
21            addRecordingButton();
22        } else {
23            console.log('Google Meet Recorder: Not on Google Meet page');
24        }
25    }
26
27    function addRecordingButton() {
28        console.log('Google Meet Recorder: In addRecordingButton function');
29        // Check if button already exists
30        if (document.getElementById('google-meet-recorder-btn')) {
31            console.log('Google Meet Recorder: Button already exists');
32            return;
33        }
34        
35        // Create the recording button
36        const recordButton = document.createElement('div');
37        recordButton.id = 'google-meet-recorder-btn';
38        recordButton.style.position = 'fixed';
39        recordButton.style.bottom = '20px';
40        recordButton.style.right = '20px';
41        recordButton.style.zIndex = '9999';
42        recordButton.style.backgroundColor = '#fff';
43        recordButton.style.border = '1px solid #dadce0';
44        recordButton.style.borderRadius = '50%';
45        recordButton.style.width = '50px';
46        recordButton.style.height = '50px';
47        recordButton.style.cursor = 'pointer';
48        recordButton.style.display = 'flex';
49        recordButton.style.alignItems = 'center';
50        recordButton.style.justifyContent = 'center';
51        recordButton.style.boxShadow = '0 1px 2px 0 rgba(60,64,67,.302), 0 1px 3px 1px rgba(60,64,67,.149)';
52        
53        // Add record icon (red circle)
54        const recordIcon = document.createElement('div');
55        recordIcon.style.width = '24px';
56        recordIcon.style.height = '24px';
57        recordIcon.style.borderRadius = '50%';
58        recordIcon.style.backgroundColor = '#ea4335';
59        recordButton.appendChild(recordIcon);
60        
61        // Add click event
62        recordButton.addEventListener('click', toggleRecording);
63        
64        // Add to document
65        document.body.appendChild(recordButton);
66        console.log('Google Meet Recorder: Recording button added to document');
67    }
68
69    async function toggleRecording() {
70        console.log('Google Meet Recorder: Toggle recording called');
71        if (!recording) {
72            startRecording();
73        } else {
74            stopRecording();
75        }
76    }
77
78    async function startRecording() {
79        console.log('Google Meet Recorder: Starting recording');
80        try {
81            // Get display media for screen recording
82            const stream = await navigator.mediaDevices.getDisplayMedia({
83                video: {
84                    width: { ideal: 1920 },
85                    height: { ideal: 1080 }
86                },
87                audio: true
88            });
89
90            // Also capture microphone audio
91            const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
92            
93            // Combine streams
94            const combinedStream = new MediaStream([
95                ...stream.getVideoTracks(),
96                ...stream.getAudioTracks(),
97                ...micStream.getAudioTracks()
98            ]);
99
100            // Create media recorder
101            mediaRecorder = new MediaRecorder(combinedStream);
102            recordedChunks = [];
103
104            mediaRecorder.ondataavailable = event => {
105                if (event.data.size > 0) {
106                    recordedChunks.push(event.data);
107                }
108            };
109
110            mediaRecorder.onstop = () => {
111                // Stop all tracks
112                stream.getTracks().forEach(track => track.stop());
113                micStream.getTracks().forEach(track => track.stop());
114                
115                // Download the recording
116                downloadRecording();
117            };
118
119            // Start recording
120            mediaRecorder.start();
121            recording = true;
122            
123            // Update button appearance
124            const button = document.getElementById('google-meet-recorder-btn');
125            const icon = button.firstChild;
126            icon.style.backgroundColor = '#fff';
127            icon.style.border = '2px solid #ea4335';
128            icon.style.borderRadius = '3px';
129            
130            console.log('Recording started');
131        } catch (error) {
132            console.error('Error starting recording:', error);
133            alert('Failed to start recording. Please check permissions.');
134        }
135    }
136
137    function stopRecording() {
138        console.log('Google Meet Recorder: Stopping recording');
139        if (mediaRecorder && recording) {
140            mediaRecorder.stop();
141            recording = false;
142            
143            // Update button appearance
144            const button = document.getElementById('google-meet-recorder-btn');
145            const icon = button.firstChild;
146            icon.style.backgroundColor = '#ea4335';
147            icon.style.border = 'none';
148            icon.style.borderRadius = '50%';
149            
150            console.log('Recording stopped');
151        }
152    }
153
154    function downloadRecording() {
155        const blob = new Blob(recordedChunks, { type: 'video/webm' });
156        const url = URL.createObjectURL(blob);
157        const a = document.createElement('a');
158        a.style.display = 'none';
159        a.href = url;
160        a.download = `google-meet-recording-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.webm`;
161        document.body.appendChild(a);
162        a.click();
163        URL.revokeObjectURL(url);
164        document.body.removeChild(a);
165        
166        console.log('Recording downloaded');
167    }
168
169    // Initialize immediately and also on DOMContentLoaded
170    if (document.readyState === 'loading') {
171        document.addEventListener('DOMContentLoaded', init);
172    } else {
173        init();
174    }
175    
176    // Also try to initialize after a delay to catch dynamic content
177    setTimeout(init, 3000);
178})();