3

Так что я пытаюсь захватить веб-аудио с вкладки и передать ее в другой скрипт, который работает с элементами DOM на странице.webkitMediaStream Тип объекта потерян при использовании sendMessage в Chrome Extension

РАСШИРЕНИЕ SCRIPT

В background.js, я использую следующий сценарий:

chrome.tabCapture.capture(constraints, function(stream) { 
     console.log("\ngot stream"); 
     console.log(stream); 

     chrome.tabs.sendMessage(tabID, { 
      "message": "stream", 
      "stream": stream 
     }); 
    }); 

Разработчик Инструментарий показывает мне, что созданный объект действительно является объектом MediaStream. (Что я хочу и, кажется, работает нормально).

РАСШИРЕНИЯ CONSOLE:

MediaStream {onremovetrack: null, onaddtrack: null, onended: null, ended: false, id: "c0jm4lYJus3XCwQgesUGT9lpyPQiWlGKHb7q"…}

СОДЕРЖАНИЕ SCRIPT

Я использую скрипт контента (впрыскивается), на самой странице в том тянуть сериализированный объект JSON обратно:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { 
    if (request.message === "stream") { 
    var thisStream = request.stream; 
    console.log(thisStream); 
    if (!thisStream) { 
     console.log("stream is null"); 
     return; 
    }  
    loadStream(thisStream); 
    } 
    else if (request.message === "statusChanged") { 
    console.log("statusChanged"); 
    } 
}); 

PAGE CONSOLE

К сожалению, из-за JSON сериализации, тип объекта теряется:

Object {onremovetrack: null, onaddtrack: null, onended: null, ended: false, id: "c0jm4lYJus3XCwQgesUGT9lpyPQiWlGKHb7q"…}

мне нужен объект переделано как объект MediaStream и попытались следующие вещи, которые потерпели неудачу:

Попытка 1: FAILED

var stream = new webkitMediaStream; 
function loadStream(thisStream) { 
    stream = thisStream; 
} 

Попытка 2: FAILED

var stream; 
function loadStream(thisStream) { 
    stream = new webkitMediaStream(thisStream); 
} 

Попытка 3: FAILED

var stream; 
function loadStream(thisStream) { 
    stream = Object.create(webkitMediaStream, thisStream); 
} 

Примечание: Конструктор для объекта MediaStreamISwebkitMediaStream.

Мне нужен либо лучший метод для передачи объекта из сценария расширения (единственного места, с которого работает метод chrome.tab.capture()), в сценарий содержимого (единственное место, где есть доступ и может изменять элементы DOM на странице) ,

ИЛИ

Мне нужна способ переделки сериализированного объекта JSON обратно в полностью функциональный MediaStream объекта.

Заранее благодарен!

JRad Плохие

ответ

2

сообщения расширения всегда JSON-сериализации, так что это действительно очевидно, что вы не можете отправить MediaStream от фона страницы на веб-странице. Вопрос в том, действительно ли вам нужно отправить MediaStream из фона в сценарий контента?

  • Если вам нужно только, например. отобразите видео, затем вы можете использовать URL.createObjectURL, чтобы получить blob: -URL для потока и назначить его video.src, чтобы посмотреть видео. URL-адрес, созданный URL.createObjectURL, может использоваться только страницей того же происхождения, поэтому вам необходимо создать тег <video> на странице chrome-extension://; либо на вкладке, либо в кадре. Если вы хотите сделать это в кадре, убедитесь, что страница указана в web_accessible_resources.

Если вы DO действительно нужен MediaStream объект на вкладке на вкладке, а затем RTCPeerConnection может быть использован для передачи потока. Этот API WebRTC обычно используется для обмена медиапотоками между одноранговыми узлами в сети, но также может использоваться для отправки потоков с одной страницы на другую страницу на другой вкладке или в браузере.

Вот полный пример. Посетите любую веб-страницу и нажмите кнопку расширения. Затем расширение добавит видео на страницу с текущей вкладкой.

background.js

function sendStreamToTab(tabId, stream) { 
    var pc = new webkitRTCPeerConnection({iceServers:[]}); 
    pc.addStream(stream); 
    pc.createOffer(function(offer) { 
     pc.setLocalDescription(offer, function() { 
      // Use chrome.tabs.connect instead of sendMessage 
      // to make sure that the lifetime of the stream 
      // is tied to the lifetime of the consumer (tab). 
      var port = chrome.tabs.connect(tabId, {name: 'tabCaptureSDP'}); 
      port.onDisconnect.addListener(function() { 
       stopStream(stream); 
      }); 
      port.onMessage.addListener(function(sdp) { 
       pc.setRemoteDescription(new RTCSessionDescription(sdp)); 
      }); 
      port.postMessage(pc.localDescription); 
     }); 
    }); 
} 

function stopStream(stream) { 
    var tracks = this.getTracks(); 
    for (var i = 0; i < tracks.length; ++i) { 
     tracks[i].stop(); 
    } 
} 

function captureTab(tabId) { 
    // Note: this method must be invoked by the user as defined 
    // in https://crbug.com/489258, e.g. chrome.browserAction.onClicked. 
    chrome.tabCapture.capture({ 
     audio: true, 
     video: true, 
     audioConstraints: { 
      mandatory: { 
       chromeMediaSource: 'tab', 
      }, 
     }, 
     videoConstraints: { 
      mandatory: { 
       chromeMediaSource: 'tab', 
      }, 
     }, 
    }, function(stream) { 
     if (!stream) { 
      alert('Stream creation failed: ' + chrome.runtime.lastError.message); 
     } 
     chrome.tabs.executeScript(tabId, {file: 'contentscript.js'}, function() { 
      if (chrome.runtime.lastError) { 
       stopStream(stream); 
       alert('Script injection failed:' + chrome.runtime.lastError.message); 
      } else { 
       sendStreamToTab(tabId, stream); 
      } 
     }); 
    }); 
} 

chrome.browserAction.onClicked.addListener(function(tab) { 
    captureTab(tab.id); 
}); 

contentscript.js

function onReceiveStream(stream) { 
    // Just to show that we can receive streams: 
    var video = document.createElement('video'); 
    video.style.border = '1px solid black'; 
    video.src = URL.createObjectURL(stream); 
    document.body.insertBefore(video, document.body.firstChild); 
} 

function onReceiveOfferSDP(sdp, sendResponse) { 
    var pc = new webkitRTCPeerConnection({iceServers:[]}); 
    pc.onaddstream = function(event) { 
     onReceiveStream(event.stream); 
    }; 
    pc.setRemoteDescription(new RTCSessionDescription(sdp), function() { 
     pc.createAnswer(function(answer) { 
      pc.setLocalDescription(answer); 
      sendResponse(pc.localDescription); 
     }); 
    }); 
} 

// Run once to prevent the message from being handled twice when 
// executeScript is called multiple times. 
if (!window.hasRun) { 
    window.hasRun = 1; 
    chrome.runtime.onConnect.addListener(function(port) { 
     if (port.name === 'tabCaptureSDP') { 
      port.onMessage.addListener(function(remoteDescription) { 
       onReceiveOfferSDP(remoteDescription, function(sdp) { 
        port.postMessage(sdp); 
       }); 
      }); 
     } 
    }); 
} 

manifest.json

{ 
    "name": "tabCapture to tab", 
    "version": "1", 
    "manifest_version": 2, 
    "background": { 
     "scripts": ["background.js"], 
     "persistent": false 
    }, 
    "browser_action": { 
     "default_title": "Capture tab" 
    }, 
    "permissions": [ 
     "activeTab", 
     "tabCapture" 
    ] 
} 
Смежные вопросы