allo- / virtual_webcam_background

Use a virtual webcam background and overlays with body-pix and v4l2loopback
GNU General Public License v3.0
306 stars 48 forks source link

Add support for Akvcam #33

Open fangfufu opened 4 years ago

fangfufu commented 4 years ago

Chrome doesn't like v4l2loopback, but Akvcam is known to work correctly with Chrome. An example script has been provided to interface with Akvcam using Python.

https://github.com/webcamoid/akvcam/issues/26#issuecomment-636848904

allo- commented 4 years ago

I have no problem with chromium (did you use the exclusive_caps option for v4l2loopback). I wonder if there is really a difference.

But I am open for more ideas, as long as they do not complicate the program too much. As scheduling the frames currently is only a small part of the code, it could probably made modular, so you can change the backend (I am looking if there is a Windows/Mac backend anyway).

allo- commented 4 years ago

The examples in https://github.com/webcamoid/akvcam/wiki/Usage-and-examples look the same as the command lines for v4l2loopback. Maybe it can just be used as drop-in replacement for v4l2loopback?

fangfufu commented 4 years ago

I think v4l2loopback expects RGB, and akvcam expects YUV2. I definitely have problem with Chrome - I haven't tried Chromium yet.

The replacement should be fairly easy, I will do that to my own Linux-Fake-Background-Webcam, when I have time. (It is still being maintained - people have been sending me pull requests)

allo- commented 4 years ago

I wonder if this can be solved by converting the RGB numpy array to YUV and keep using pyfakewebcam.

chrome and chromium should behave the same, except for some Google integration, the updater and the PDF reader.

I also tried with electron apps, but that's chromium, too.

allo- commented 4 years ago

pyfakewebcam does exactly this, see https://github.com/jremmons/pyfakewebcam/blob/master/pyfakewebcam/pyfakewebcam.py

allo- commented 4 years ago

What framerate do you achieve? I think chrome only recognizes cams that provide a certain framerate like 5 fps or so.

This may be a cause for problems with chrome. And this could possibly avoided by duplicating frames, this would need some experimentation. Especially how the frame rate is measured, so if you are allowed to send 5 frames at once and then process the next one for a second or if you need a thread to send the duplicates with some time in between. I think v4l2loopback (no idea about akvcam) can configure a framerate, maybe this leads to buffering the frames that are too fast.

fangfufu commented 4 years ago

I think I achieve about 8fps or something, there is a thread about why Chrome doesn't work with v4l2loopback. (https://github.com/umlaeute/v4l2loopback/issues/78)

allo- commented 4 years ago

Interesting thread and linked issues, but I see no clear resolution either. Some posts sound like it could be an issue with the driver version (I am using debian testing with version 0.12.5).

Did you test akvcam and it works reliable for you? I did not test it, yet.

fangfufu commented 4 years ago

Akvcam worked fine for me. There seems to be some instability issue, but it works mostly fine.

allo- commented 4 years ago

Do you want to open an issue in the pyfakewebcam project? Maybe more users can profit from pyfakewebcam supporting akvcam as well.

fangfufu commented 4 years ago

Hmm, I am a bit busy right now. Feel free to open an issue. I reckon it would be easier to just modify the code and submit a pull request.

allo- commented 4 years ago

I first want to test akvcam myself. I got the kernel module working, now I need to experiment with client code.

fangfufu commented 4 years ago

@allo- , FWIW, I was chatting to some random people on my old university's IRC channel, they all complained about v4l2loopback not working with Ubuntu properly... So I think I will try and integrate Akvcam to my scripts by the end of this week.

allo- commented 4 years ago

I did only try it on debian testing yet. When your code snippet is working, I can probably integrate it. @drjerk1 should probably add a license to this post or create a small project for it, though.

drjerk1 commented 4 years ago

@allo- you can intergrate it if you want, but i copy pasted some parts of it from other github sources

allo- commented 4 years ago

@drjerk1 Are there some projects that can already be used? I am still thinking if it should be integrated into pyfakewebcam or a fork of it.

drjerk1 commented 4 years ago

@allo- I wrote it for my university project, which can swap faces in the video based on single photo, like deepfake do but with less quality, which i will publish in some time

allo- commented 4 years ago

@drjerk1 This sounds like an interesting project.

But with my question I hoped that you may know some module where parts of the code are from, that can be used.

But maybe your code can be built into a simple module like the pyfakewebcam module. I need some more time to experiment with it before I know how I would like to use it.

drjerk1 commented 4 years ago

@allo- sadly i've no experience working with virtual cameras before, but i think that it can write to any fake webcam driver because linux files like /dev/video1 provides universal api themselfs (with close, open, ioctl syscalls), it just writes bytes to file and opens it properly

fangfufu commented 4 years ago

Just for the record, I added akvcam support on my implementation, please feel free to steal my code. I think the main thing is the configuration file in /etc/akvcam, it needs to have rw support. Akvcam is pretty much a drop-in replacement for v4l2loopback.

allo- commented 4 years ago

I'ill have a look.

allo- commented 4 years ago

@fangfufu you seem to have a typo here: https://github.com/fangfufu/Linux-Fake-Background-Webcam/blob/master/fakecam/akvcam.py#L57 When you tested using this code, you'll probably have swapped colors without the typo.

fangfufu commented 4 years ago

Nope, that's intended. OpenCV reads stuff in BGR format.

fangfufu commented 4 years ago

If you look at https://github.com/fangfufu/Linux-Fake-Background-Webcam/blob/master/fakecam/fake.py, and look for akvcam in the source code, you would see that the changes I made are minimal.

allo- commented 4 years ago

Are you sure that the unused variable iamge is intended? You have typo in the variable name and because of this the converted frame is never used.

When the frame looks good nevertheless, you can probably just remove the line and the frame does not need to be converted at this place.

I need to test it in detail later. I just noticed the typo there and that your code is not using the converted frame.

fangfufu commented 4 years ago

Ah yes, you are right, there is a typo. I definitely could not read... I tested the class itself with fake.py it works really well. Anyways, the colour is a bit off when I run the example script... I suppose it is just that I hadn't run the example script for a while.

allo- commented 4 years ago

I need more time to test such stuff. I forked pyfakewebcam after the author added a note that it's unmaintained. Maybe it would be useful to merge it there. But your class looks like it can be used as drop-in replacement, so I can just add it to the project and load the right module for the driver the user is using.

fangfufu commented 4 years ago

Well I think somebody needs to maintain pyfakewebcam. But adding my class is pretty much minimal effort. It doesn't really matter which way you go about it - I just think akvcam is superior than v4l2loopback.

allo- commented 4 years ago

After reading in the pyfakewebcam source that looks very similar to your code, I found out that you can just configure akvcam to use YUYV2 as format.

Adapted from https://github.com/webcamoid/akvcam/wiki/Configure-the-cameras I just removed the RGB24 format as input format:

This config works without any modifications of my code:

[Cameras]
cameras/size = 2 

cameras/1/type = output
cameras/1/mode = mmap, userptr, rw
cameras/1/description = Virtual Camera (output device)
cameras/1/formats = 2 

cameras/2/type = capture
cameras/2/mode = mmap, rw
cameras/2/description = Virtual Camera
cameras/2/formats = 1, 2

[Formats]
formats/size = 2 

formats/1/format = YUY2
formats/1/width = 640
formats/1/height = 480
formats/1/fps = 30

formats/2/format = YUY2
formats/2/width = 640
formats/2/height = 480
formats/2/fps = 20/1, 15/2

[Connections]
connections/size = 1 
connections/1/connection = 1:2
fangfufu commented 4 years ago

You are literally contradicting what hipersayanX said. Are you sure it works?

fangfufu commented 4 years ago

Okay it seems other people have reported similar experience as you.

allo- commented 4 years ago

I worked a few minutes ago when I tested it ;-).

Maybe the akvcam docs are a bit outdated?

fangfufu commented 4 years ago

I feel hipersayanX isn't exactly sure what his code does. ;) He literally told me that the output device only takes RGB24 as input...

fangfufu commented 4 years ago

I am sticking with my implementation anyway, it does fewer colour space conversion.

fangfufu commented 4 years ago

@allo- , look: https://github.com/webcamoid/akvcam/issues/26#issuecomment-638326191

allo- commented 4 years ago

I do not know why it works, but it works. And the example config in the Wiki has RGB24, YUY2 what looks like it is offering both (and preferring RGB24?).

I think I rather document how to configure akvcam, so I do not need to duplicate code that is almost the same in pyfakewebcam.

I may reconsider implementing it directly, when the frame conversion becomes the bottleneck.

The code in https://github.com/webcamoid/akvcam/issues/26#issuecomment-636848904 looks VERY similar to pyfakewebcam.py and both seem to do the color conversion using img_yuv = cv2.cvtColor(image, cv2.COLOR_RGB2YUV). Pyfakewebcam has in addition a numpy-only fallback, but the rest looks similar. I am not absolutely sure about all the reshape/concatenate operations in the two codes, but I guess they should have the same result in the end.

fangfufu commented 4 years ago

The reshape and concatenate are done because of this: https://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec/re09.html

I am going to stick to my code and let akvcam to handle all the nonsense. My super long config file was actually generated by webcamoid. I want to config to be compatible with webcamoid as well.

allo- commented 4 years ago

I suppose the reshaping in your code and the copying into the buffer in the pyfakewebcam code are equivalent. But I am not too motivated to verify if it is really the same as long as the resulting image is the same.

allo- commented 4 years ago

Good to know that webcamoid can generate configs. I will see what I'll add for documentation.

I'll come back at your code, if there are problems with my approach or reasons why it should be handled in another way. I think the rest of our data formats keep compatible (RGB / BGR frames) anyway and the schedule frame part can be swapped out for something else at any time.

allo- commented 4 years ago

When the processing is too slow, the standby frame is flashing when using akvcam, while v4l2loopback just is slowed down (as it is just a loopback).

@fangfufu Does your implementation solve this problem?

fangfufu commented 4 years ago

Ohh, I encountered the same problem as well! No, I haven't managed to solve it! It happened to me only once.

allo- commented 4 years ago

I guess there is some minimum frame rate, which may be configurable?

fangfufu commented 4 years ago

I have absolutely no idea...

fangfufu commented 4 years ago

Actually you can set the frame rates here: https://github.com/webcamoid/akvcam/wiki/Configure-the-cameras

Considering we are just writing stuff to akvcam, if we stop writing, it is reasonable for akvcam to revert to the default screen.

fangfufu commented 3 years ago

Okay, I am adopting your config file to support Akvcam on my end.

allo- commented 3 years ago

So what do you think do we need for this issue? Maybe just adding a akvcam example config file?

fangfufu commented 3 years ago

I have always shipped a config file. I have adjusted my config file to look very similar to yours.

https://github.com/fangfufu/Linux-Fake-Background-Webcam/blob/master/akvcam/config.ini

But yes, with this config file, you can use pyfakewebcam to output directly to Akvcam.