diff --git a/offscreen/index.html b/offscreen/index.html
deleted file mode 100644
index f0d3d66..0000000
--- a/offscreen/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- Offscreen Page
-
-
-
-
-
\ No newline at end of file
diff --git a/offscreen/index.ts b/offscreen/index.ts
deleted file mode 100644
index 0621aa2..0000000
--- a/offscreen/index.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-let mediaRecorder: MediaRecorder | null = null;
-let videoChunks: Blob[] = [];
-
-// Запись видео
-async function startRecording(streamId: string) {
- const stream = await navigator.mediaDevices.getUserMedia({
- video: {
- mandatory: {
- chromeMediaSource: 'tab',
- chromeMediaSourceId: streamId
- }
- } as any,
- audio: false
- });
-
- mediaRecorder = new MediaRecorder(stream);
-
- mediaRecorder.ondataavailable = (event) => {
- if (event.data && event.data.size > 0) {
- videoChunks.push(event.data);
- chrome.runtime.sendMessage({
- type: 'VIDEO_CHUNK',
- data: event.data,
- timestamp: Date.now()
- });
- }
- };
-
- mediaRecorder.start(1000);
-}
-
-// Остановка записи
-function stopRecording() {
- if (mediaRecorder && mediaRecorder.state !== 'inactive') {
- mediaRecorder.stop();
- }
-}
-
-// Получение чанков
-function getChunks(): Blob[] {
- return videoChunks;
-}
-
-// Обработка сообщений
-chrome.runtime.onMessage.addListener((message) => {
- switch (message.type) {
- case 'START_RECORDING':
- startRecording(message.streamId);
- break;
- case 'STOP_RECORDING':
- stopRecording();
- break;
- case 'GET_CHUNKS':
- chrome.runtime.sendMessage({
- type: 'CHUNKS_RESPONSE',
- chunks: getChunks()
- });
- break;
- }
-});
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 4c94919..a41d252 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,6 @@
-import { defineConfig } from 'vite'
-import { crx } from '@crxjs/vite-plugin'
-import manifest from './manifest.json'
+import { defineConfig } from 'vite';
+import { crx } from '@crxjs/vite-plugin';
+import manifest from './manifest.json';
export default defineConfig({
plugins: [
@@ -10,218 +10,12 @@ export default defineConfig({
injectCss: false,
},
}),
- {
- name: 'copy-offscreen',
- generateBundle() {
- this.emitFile({
- type: 'asset',
- fileName: 'offscreen/index.html',
- source: `
-
-
-
-
- Offscreen Page
-
-
-
-
-
-`
- });
- this.emitFile({
- type: 'asset',
- fileName: 'assets/offscreen.js',
- source: `
-let mediaRecorder = null;
-let videoChunks = [];
-let chunkCount = 0;
-
-// IndexedDB для хранения видеочанков
-let db = null;
-
-function openIndexedDB() {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open('VideoRecorderDB', 1);
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => {
- db = request.result;
- resolve(db);
- };
-
- request.onupgradeneeded = (event) => {
- const db = event.target.result;
- if (!db.objectStoreNames.contains('chunks')) {
- db.createObjectStore('chunks', { keyPath: 'id' });
- }
- };
- });
-}
-
-async function saveChunkToIndexedDB(blob, chunkId) {
- if (!db) {
- await openIndexedDB();
- }
-
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(['chunks'], 'readwrite');
- const store = transaction.objectStore('chunks');
-
- const request = store.put({
- id: chunkId,
- data: blob,
- timestamp: Date.now()
- });
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => {
- console.log('[Offscreen] Chunk', chunkId, 'saved to IndexedDB, size:', blob.size);
- // Отправляем уведомление в Service Worker
- chrome.runtime.sendMessage({
- type: 'VIDEO_CHUNK_SAVED',
- chunkId: chunkId,
- size: blob.size
- });
- resolve();
- };
- });
-}
-
-async function clearOldChunks() {
- if (!db) {
- await openIndexedDB();
- }
-
- return new Promise((resolve, reject) => {
- const transaction = db.transaction(['chunks'], 'readwrite');
- const store = transaction.objectStore('chunks');
- const request = store.clear();
-
- request.onerror = () => reject(request.error);
- request.onsuccess = () => {
- console.log('[Offscreen] Cleared old chunks from IndexedDB');
- resolve();
- };
- });
-}
-
-chrome.runtime.onMessage.addListener((message) => {
- console.log('[Offscreen] Received message:', message.type);
- switch (message.type) {
- case 'START_RECORDING':
- startRecording(message.streamId);
- break;
- case 'STOP_RECORDING':
- stopRecording();
- break;
- }
-});
-
-async function startRecording(streamId) {
- console.log('[Offscreen] Starting recording with streamId:', streamId);
-
- // Инициализируем IndexedDB
- await openIndexedDB();
- console.log('[Offscreen] IndexedDB initialized');
-
- // Очищаем старые чанки
- await clearOldChunks();
-
- try {
- const stream = await navigator.mediaDevices.getUserMedia({
- video: {
- mandatory: {
- chromeMediaSource: 'tab',
- chromeMediaSourceId: streamId
- }
- },
- audio: false
- });
-
- console.log('[Offscreen] Stream created, tracks:', stream.getTracks().length);
- const videoTrack = stream.getVideoTracks()[0];
- if (videoTrack) {
- console.log('[Offscreen] Video track settings:', videoTrack.getSettings());
- console.log('[Offscreen] Video track readyState:', videoTrack.readyState);
- console.log('[Offscreen] Video track enabled:', videoTrack.enabled);
- }
-
- // Пробуем разные кодеки
- const codecs = [
- 'video/webm; codecs=vp9',
- 'video/webm; codecs=vp8',
- 'video/webm; codecs=h264',
- 'video/webm'
- ];
-
- let mediaRecorder = null;
- for (const codec of codecs) {
- try {
- mediaRecorder = new MediaRecorder(stream, { mimeType: codec });
- console.log('[Offscreen] MediaRecorder created with codec:', codec, 'state:', mediaRecorder.state);
- break;
- } catch (e) {
- console.log('[Offscreen] Codec', codec, 'not supported:', e.message);
- }
- }
-
- if (!mediaRecorder) {
- mediaRecorder = new MediaRecorder(stream);
- console.log('[Offscreen] Using default MediaRecorder');
- }
-
- mediaRecorder.ondataavailable = (event) => {
- console.log('[Offscreen] Data available:', event.data.size, 'bytes, type:', event.data.type);
- if (event.data && event.data.size > 0) {
- chunkCount++;
- console.log('[Offscreen] Sending chunk', chunkCount, 'to background, size:', event.data.size);
-
- // Сохраняем в indexedDB вместо передачи через сообщения
- saveChunkToIndexedDB(event.data, chunkCount);
- } else {
- console.log('[Offscreen] Data available but size is 0, skipping');
- }
- };
-
- mediaRecorder.onerror = (event) => {
- console.error('[Offscreen] MediaRecorder error:', event);
- };
-
- mediaRecorder.onstart = () => {
- console.log('[Offscreen] MediaRecorder started, state:', mediaRecorder.state);
- };
-
- mediaRecorder.onstop = () => {
- console.log('[Offscreen] MediaRecorder stopped, state:', mediaRecorder.state, 'total chunks:', chunkCount);
- };
-
- // Используем интервал 200мс для более частого получения чанков с ключевыми кадрами
- mediaRecorder.start(200);
- console.log('[Offscreen] Recording started with interval 200ms');
- } catch (error) {
- console.error('[Offscreen] Error starting recording:', error);
- }
-}
-
-function stopRecording() {
- if (mediaRecorder && mediaRecorder.state !== 'inactive') {
- mediaRecorder.stop();
- console.log('[Offscreen] Recording stopped');
- }
-}
-`
- });
- }
- }
],
build: {
rollupOptions: {
- output: {
- manualChunks: undefined
- }
+ input: {
+ offscreen: 'src/offscreen/index.html',
+ },
},
- copyPublicDir: true,
- publicDir: 'public',
- }
-})
\ No newline at end of file
+ },
+});