Run Chromium with fake webcam and real micro - google-chrome

I can run the Google Chrome with the fake webcam using this command:
$ google-chrome-stable --use-fake-device-for-media-stream --use-file-for-fake-video-capture=video.mjpeg
This works fine, but I can only use fake audio sources using this configuration. How to run Chromium/Google Chrome with fake video stream and real audio stream?
Also you can use any Python modules you want.

With --use-fake-device-for-media-stream it is not possible, Chrome will always use fake audio:
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream)) {
params_.set_format(media::AudioParameters::AUDIO_FAKE);
}
Use a virtual webcam and your real microphone instead.
A quick selection from searching:
Webcamoid, Windows/macOS/Linux
OBS Virtualcam, plugin for OBS Studio, Windows/macOS/Linux
Syphon Virtual Webcam, plugin for Isadora, macOS

Related

How can I correctly provide a mock webcam video to Chrome?

I'm trying to run end-to-end testing in Chrome for a product that requires a webcam feed halfway through to operate. From what I understand this means providing a fake webcam video to Chrome using the --use-file-for-fake-video-capture="/path/to/video.y4m" command line argument. It will then use that as a webcam video.
However, no matter what y4m file I provide, I get the following error from Chrome running under these conditions:
DOMException: Could not start video source
{
code: 0,
message: "Could not start video source",
name: "NotReadableError"
}
Notably I can provide an audio file just fine using --use-file-for-fake-audio-capture and Chrome will work with it well. The video has been my sticking point.
This error comes out of the following straightforward mediaDevices request:
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(data => {
// do stuff
})
.catch(err => {
// oh no!
});
(This always hits the “oh no!” branch when a video file is provided.)
What I've tried so far
I've been running Chrome with the following command line arguments (newlines added for readability), and I'm using a Mac hence the open command:
open -a "Google Chrome" --args
--disable-gpu
--use-fake-device-for-media-stream
--use-file-for-fake-video-capture="~/Documents/mock/webcam.y4m"
--use-file-for-fake-audio-capture="~/Documents/mock/microphone.wav"
webcam.y4m and microphone.wav were generated from a video file I recorded.
I first recorded a twenty-second mp4 video using my browser's MediaRecorder, downloaded the result, and converted it using the following command line commands:
ffmpeg -y -i original.mp4 -f wav -vn microphone.wav
ffmpeg -y -i original.mp4 webcam.y4m
When this didn't work, I tried the same using a twenty-second movie file I recorded in Quicktime:
ffmpeg -y -i original.mov -f wav -vn microphone.wav
ffmpeg -y -i original.mov webcam.y4m
When that also failed, I went straight to the Chromium file that explains fake video capture, went to the example y4m file list it provided, and downloaded the grandma file and provided that as a command line argument to Chrome instead:
open -a "Google Chrome" --args
--disable-gpu
--use-fake-device-for-media-stream
--use-file-for-fake-video-capture="~/Documents/mock/grandma_qcif.y4m"
--use-file-for-fake-audio-capture="~/Documents/mock/microphone.wav"
Chrome provides me with the exact same error in all of these situations.
The only time Chrome doesn't error out with that mediaDevices request is when I omit the video completely:
open -a "Google Chrome" --args
--disable-gpu
--use-fake-device-for-media-stream
--use-file-for-fake-audio-capture="~/Documents/mock/microphone.wav"
Accounting for C420mpeg2
TestRTC suggests Chrome will “crash” if I give it a C420mpeg2 file, and recommends that simply replacing the metadata fixes the issue. Indeed the video file I generate from ffmpeg gives me the following header:
YUV4MPEG2 W1280 H720 F30:1 Ip A1:1 C420mpeg2 XYSCSS=420MPEG2
Chrome doesn't actually crash when run with this file, I just get the error above. If I edit the video file to the following header though per TestRTC's recommendations I get the same situation:
YUV4MPEG2 W1280 H720 F30:1 Ip A1:1 C420 XYSCSS=420MPEG2
The video file still gives me the above error in these conditions.
What can/should I do?
How should I be providing a video file to Chrome for this command line argument?
How should I be recording or creating the video file?
How should I convert it to y4m?
After reading the link you provided I noticed that we can also provide an mjpeg.
Depending on what your test requirements - this may be sufficient for you. As a terminal command with ffmpeg installed:
ffmpeg -i oldfile.mp4 newfile.mjpeg
then I tested by running Google Chrome from the terminal using:
google-chrome --use-fake-device-for-media-stream --use-file-for-fake-video-capture=newfile.mjpeg
After navigating to Tracking JS I could see the video being played back.
I hope that works for you!
If someone ever needs to mock a video dynamically, this is what I've used (forked from here)
await page.evaluate(() => {
const video = document.createElement("video");
video.setAttribute('id', 'video-mock');
video.setAttribute("src", 'https://woolyss.com/f/spring-vp9-vorbis.webm');
video.setAttribute("crossorigin", "anonymous");
video.setAttribute("controls", "");
video.oncanplay = () => {
const stream = video.captureStream();
navigator.mediaDevices.getUserMedia = () => Promise.resolve(stream);
};
document.querySelector("body").appendChild(video);
});
the key is to return Promise.resolve(stream)
oncanplay is better than onplay because it is triggered after the video is playable
This flags are still necessary:
'--use-fake-ui-for-media-stream',
'--use-fake-device-for-media-stream',
In the end, with this script different camera mocks are possible for every page - especially useful when using browserless!
Mocked/Fake Raw Video (2021)
Use y4m if you want raw frames without Chrome having to run a decoder:
ffmpeg -i original.avi -pix_fmt yuv420p video-for-chrome.y4m
Then, start Chrome:
chrome.exe --use-fake-device-for-media-stream --use-file-for-fake-video-capture=video-for-chrome.y4m
Note: There is no longer any reason to have to modify your y4m file's header. Chrome has since been fixed.
This method uses less CPU, but will take up a good deal of hard drive space for the raw video. Keep your video file short. Chrome will loop it.
How to mock webcam on Chrome for Windows
(Tested with Windows 10 Home Build 19043.1526 and Chrome Version 98.0.4758.102 (Official Build) (64-bit))
Install ffmpeg, then run the following command in your shell to convert your mp4 to mpjeg:
./ffmpeg.exe -i originalVideo.mp4 output.mjpeg
Alternatively, you could also create a y4m video from a png image (thanks #LGenzelis):
./ffmpeg.exe -loop 1 -i myStaticImage.png -pix_fmt yuv420p -t 0.05 output.y4m
Close all Chrome instances, then run the following command in your shell:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --use-fake-device-for-media-stream --use-file-for-fake-video-capture="C:/absolute/path/to/output.mjpeg"
Then test it on a website like https://webcamtests.com/
Troubleshooting
Chrome still showing stream from real camera
Make sure there are no other Chrome instances running before launching it with those arguments.
Camera not found
Make sure you're providing the absolute path to your video in --use-file-for-fake-video-capture (e.g.: "C:/absolute/path/to/output.mjpeg" instead of just output.mjpeg)

Chromium --alsa-ouput-device flag not working

I have created a virtual alsa loopback device and trying to open a youtube link in google-chrome or chromium-browser and trying to send it's audio output to that virtual device. Then using ffmpeg I am trying to capture the audio. But no matter what I do, chrome or chromium always send audio output to default built-in speakers. If I open volume control panel and change the output of the application in playback section to loopback then it works. But my requirement to be able to do it programatically by telling the chrome to send audio on which device.
Following are the commands which I tried to make it happen:
google-chrome --window-position=0,0 --window-size=1920,1080 --alsa-output-device=alsa_output.1.analog-stereo.monitor -kiosk https://www.youtube.com/watch?v=LTbnmiXWs2k
google-chrome --window-position=0,0 --window-size=1920,1080 --alsa-output-device=hw:1,0 -kiosk https://www.youtube.com/watch?v=LTbnmiXWs2k
And following is the ffmpeg command which is working fine:
ffmpeg -f pulse -i alsa_output.1.analog-stereo.monitor -ac 1 -ar 16000 test.wav
Any help will be appreciated.
I have also suffered from the same problem, as Google didn't provide the complete format for ALSA output usage, so you can follow below procedure,
list out the plug hardware:
aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
pulse
PulseAudio Sound Server
default:CARD=PCH
HDA Intel PCH, ALC662 rev3 Analog
Default Audio Device
sysdefault:CARD=PCH
HDA Intel PCH, ALC662 rev3 Analog
Default Audio Device
front:CARD=PCH,DEV=0
HDA Intel PCH, ALC662 rev3 Analog
Front speakers
surround21:CARD=PCH,DEV=0
HDA Intel PCH, ALC662 rev3 Analog
2.1 Surround output to Front and Subwoofer speakers
Now select your plug hardware from the list and add its name to --alsa-output-device=
--alsa-output-device='plug:surround21'
so your complete command will look like below,
google-chrome --window-position=0,0 --window-size=1920,1080 --alsa-output-device='plug:surround21' -kiosk https://www.youtube.com/watch?v=LTbnmiXWs2k
I faced the same problem while attempting to do the same. Here's what actually worked:
chrome (...) --alsa-output-device=hw:0,0
ffmpeg -f alsa -ac 2 -i hw:0,1,1 test.wav
This has chrome using (card 0, device 0) for output, which is looped back to (card 0, device 1, substream 1). The format is --alsa-output-device=hw:card,device
The opposite also works:
chrome (...) --alsa-output-device=hw:0,1
ffmpeg -f alsa -ac 2 -i hw:0,0,1 test.wav
Selecting the substream (e.g. --alsa-output-device=hw:0,1,4) is impossible. If capturing with ffmpeg just assume substream 1.

Chrome Adobe Flash is out of date

I keep getting this browser (chrome) notification saying
Adobe Flash Player was blocked because it is out of date. Update, Run This Time
If I click run this time it allows me to run any flash content on current page but same notification on new page. If however, I click update plugin it takes me to this Chrome support page. I follow instructions and go to chrome://plugins which give me a url under Adobe Flash Player which is following Download Critical Security Update and as you see this again links me to the Google support page with instructions on how to update and that I've already been on.
I encountered the same issue with Chrome on my Linux system.
Here is my solution for Linux system:
Install chrome 55+, if you have an older version.
Download flash player,
url: http://get.adobe.com/flashplayer/
step 1 - os
choose "linux 64 bit",
step 2 - version
choose "FP xx for linux 64-bit (.tar.gz) - PPAPI",
Download,
Uncompress,
Copy files in the directory into ~/.config/google-chrome/PepperFlash/,
Make it executable via: chmod +x libpepflashplayer.so
Append parameter to chrome's start command,
Where is the command:
(1) for icon,
right click icon -> properties, there is "command" input,
(2) for shortcut,
config the shortcut,
The parameter to append is:
--ppapi-flash-path=/home/eric/.config/google-chrome/PepperFlash/libpepflashplayer.so
e.g.
/usr/bin/google-chrome-stable %U --ppapi-flash-path=/home/eric/.config/google-chrome/PepperFlash/libpepflashplayer.so
Restart chrome,
Now the flash should work.
I assume you have solved your issue by now, but for the benefit of others: Flash is now provided as a so-called component and updated separately from the main Chrome application. I would therefore suggest first checking chrome://components and manually check for an update there.
By the way, the same is true for the Widevine DRM component, which if not up-to-date may stop Netflix, etc. from running.

How can I make Chrome allow access to a webcam over http (not https)?

I am building a kiosk application using webrtc video. It is only served on the internal network and I would like to be able to always allow the webcam for my site over http. Using ssl isn't that important and is just an extra expense for a cert.
Is there any way to do this or am I stuck?
Yes, an admin can override the prompts with a policy.
VideoCaptureAllowedUrls
Patterns in this list will be matched against the security origin of the requesting URL. If a match is found, access to audio capture devices will be granted without prompt. NOTE: This policy is currently only supported when running in Kiosk mode.
On Windows, you create registry entries using regedit.
Software\Policies\Chromium\VideoCaptureAllowedUrls\1 = "http://www.example.com/"
Software\Policies\Chromium\VideoCaptureAllowedUrls\2 = "http://[*.]example.edu/"
On Linux you write the policies in a file:
mkdir -p /etc/opt/chrome/policies/managed
touch /etc/opt/chrome/policies/managed/test_policy.json
In test_policy.json:
{
"VideoCaptureAllowedUrls": ["http://www.example.com/", "http://[*.]example.edu/"]
}
Use command-line flag
use --use-fake-ui-for-media-stream command-line flag
example (OS X) : /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome http://html5-demos.appspot.com/static/getusermedia/record-user-webm.html --use-fake-ui-for-media-stream
More info here http://creativcoders.wordpress.com/2014/08/18/chrome-always-allow-access-to-webcam-and-microphone-over-http-webrtc/
More detailed solution.
In command line, target your browser and add after your instruction the --use-fake-ui-for-media-stream flag, like this:
//On windows
#Normal mode
start chrome "http://localhost" --use-fake-ui-for-media-stream
#Kiosk mode (full screen)
start chrome --kiosk "http://localhost" --use-fake-ui-for-media-stream
For Linux and Mac command line instructions, see this: https://creativcoders.wordpress.com/2014/08/18/chrome-always-allow-access-to-webcam-and-microphone-over-http-webrtc/
Right-click the webcam capturer
If you already allow just tick "remember"

Any way to start Google Chrome in headless mode?

I carefully revised the list of switches at http://peter.sh/experiments/chromium-command-line-switches/#chrome-frame and I couldn't find anything that would launch Chrome in a hidden background process.
The closest I was able to is --keep-alive-for-test + custom packaged app, but the app fails to execute any passed code because (the way it reports) "no window - ChromeHidden".
TL;DR
google-chrome --headless --remote-debugging-port=9222 http://example.com
You'd also need --disable-gpu temporarily.
Tutorial:
https://developers.google.com/web/updates/2017/04/headless-chrome
There's a work in progress: https://code.google.com/p/chromium/issues/detail?id=546953
The main deliverables are:
A library which headless applications can link to to.
A sample application which demonstrates the use of headless APIs.
So it would be possible to create a simple application that runs in console without connecting to display.
Update Apr 18 '16: The work is mainly done. There's a public forum now:
https://groups.google.com/a/chromium.org/forum/#!forum/headless-dev
Documentation is being in progress:
https://chromium.googlesource.com/chromium/src/+/master/headless/README.md
Update Sep 20 '16: It looks like chrome will eventually get the "--headless" parameter:
https://bugs.chromium.org/p/chromium/issues/detail?id=612904
There was a presentation on BlinkOn 6 (June 16/17, 2016)
Update Nov 29 '16: Design doc for --headless flag: https://docs.google.com/document/d/1aIJUzQr3eougZQp90bp4mqGr5gY6hdUice8UPa-Ys90/edit#heading=h.qxqfzv2lj12s
Update Dec 13 '16: --headless flag is expected to be available in Canary builds soon
Update Mar 12 '17: Chrome 57 has a --headless flag working. Waiting for Selenium and other tools to catch up. User guide: https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
This guy managed to run Chrome headlessly by using Xvfb (X virtual frame buffer) to trick Chrome into thinking it was displaying a window:
http://e-method.blogspot.fr/2010/11/google-chrome-with-xvfb-headless-server.html
If you're on Linux you could try that.
So basically you need to install X virtual frame buffer and Google Chrome via:
root#localhost: ~# apt-get install xvfb imagemagick
root#localhost: ~# apt-get install google-chrome
Then run the browser on the display:
root#localhost: ~# xvfb-run --server-args='-screen 0, 1024x768x24' \
google-chrome -start-maximized http://www.example.com \
> & /dev/null &
root#localhost: ~# DISPLAY=:99 import -window root myimage.png
Or you can look at PhantomJS project which is a headless WebKit implementation.
You could set up a linux VM and use xvfb in it.
Installation on debian / ubuntu:
sudo aptitude install xvfb
Start Chrome headless and visit http://example.com :
xvfb-run --server-args='-screen 0, 1024x768x16' google-chrome
-start-maximized http://example.com > /dev/null &
Turns out it starts in headless mode if you start it as a child subprocess. Besides that:
nircmd.exe can do win hide on chrome based on its PID
Autohotkey_L can also start Chrome hidden without a taskbar button
The Chromium Embedded Framework project seems like it might fit your usecase. I don't have personal experience with the project, but I've heard good things, and it has a solid API that you should be able to exploit for your purposes.
I don't have enough reputation to comment yet, but want to let you guys know that the chrome headless mode which Vanuan mentions actually works with Selenium webdriver.
In Java you can pass the flag to chrome through chromeDriver with the following code:
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
ChromeDriver chromeDriver = new ChromeDriver(options);
I've recently found this article which mentions several commandline options that seem to do it. Using these keywords I googled out this piece of code which seem to confirm that these options exist.
// Does not automatically open a browser window on startup (used when
// launching Chrome for the purpose of hosting background apps).
const char kNoStartupWindow[] = "no-startup-window";
// Causes Chrome to launch without opening any windows by default. Useful if
// one wishes to use Chrome as an ash server.
const char kSilentLaunch[] = "silent-launch";
I managed to successfuly run Chrome with --no-startup-window and indeed it launched without any windows. It looked like it launched properly, it spawned all typical children, but the website I tried to make it load inside didn't seem to be actually visited. It maybe possible that this headless mode is only for running apps and not for visiting sites headless*), but it looks very promising as the normal worker tree is set up, just no windows.
The second option --silent-launch made chrome process very silent. I didn't notice any children spawned and the process exited promptly. I doubt it'll be usable for this case.
After I failed my attempts with these options, I focused on less sophisticated ways. On the bottom of the list there are two options:
// Specify the initial window position: --window-position=x,y
const char kWindowPosition[] = "window-position";
// Specify the initial window size: --window-size=w,h
const char kWindowSize[] = "window-size";
I ran Chrome with options to move it completely out of the working area:
--window-size=800,600 --window-position=-800,0
and as dirty as it feels, sure it's no true headless, but still the window is out of my sight, and everything done just with chrome's startup options, without external tools sending low-level window-hide messages.
*) yes, I know try to do weird things. Essentially I tried to get rid of Chrome window that's kept by Karma during tests. I know I can switch to PhantomJS, but I specifically needed to run them in Chrome, and the window popping out was.. eh.. disturbing in the long run.
It is currently under development, you can read more information about it from here:
https://chromium.googlesource.com/chromium/src/+/master/headless/README.md
Headless Chromium is a library for running Chromium in a
headless/server environment. Expected use cases include loading web
pages, extracting metadata (e.g., the DOM) and generating bitmaps from
page contents -- using all the modern web platform features provided
by Chromium and Blink.
It currently works on Linux, there is a nice presentation.
I was also able to make chrome headless work with NightwatchJS. Here is the config that let me use it:
"chromeHeadless": {
"desiredCapabilities": {
"browserName": "chrome",
"chromeOptions": {
"args": ["--headless"],
"binary": "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
}
}
}
Chrome 59 has the ability to create instance as headless.
Find the below tutorial
https://www.automation99.com/2017/07/how-to-use-chrome-headless-using.html?m=1