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