Cannot open installed OBS camera when running from a service
Closed this issue · 3 comments
- Operating system: Winwdows 10
- pyvirtualcam version: 0.8.0
- Virtual camera (OBS, v4l2loopback, UnityCapture): OBS
- Virtual camera version: win-dshow
Decription
Using pywin32==301 and auto-py-to-exe==2.9.0 to install pyvirtualcam as Windows service, I'm getting following error:
'obs' backend: virtual camera output could not be started
To Reproduce
def main():
try:
with pyvirtualcam.Camera(width=1280, height=720, fps=20, backend='obs') as cam:
print(f'Using virtual camera: {cam.device}\n')
frame = np.zeros((cam.height, cam.width, 3), np.uint8) # RGB
while True:
frame[:] = cam.frames_sent % 255 # grayscale animation
cam.send(frame)
cam.sleep_until_next_frame()
except Exception as e:
with open(r"C:\ProgramData\error.txt", 'a') as f:
f.write(str(e)+'\n')
class Service(win32serviceutil.ServiceFramework):
_svc_name_ = "TEST_VID0"
_svc_display_name_ = "test video zeros 0"
def __init__(self, *args):
# win32serviceutil.ServiceFramework.__init__(self, *args)
super().__init__(*args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(5)
self.stop_requested = False
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
self.stop_requested = True
def SvcDoRun(self):
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.main()
def main(self):
main()
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(Service)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(Service)
- compile
main()
function using auto-py-to-exe - works like a charm (writing to programdata requires administrative priveleges, so it's recommended to start exe as admin, or change destination folder to where all users can write), you should see in any camera preview gray screen that changes color - then compile whole file using auto-py-to-exe and use
file.exe install
thenfile.exe start
, you should see specified error in the text file - C:\ProgramData\error.txt
NOTE: It's not first time when i'm using pywin32 to install python programs as a service, it definetely works, provided code is a default code to create any service which main loop lies in main() function. To delete service use file.exe remove
. My guess is that system services somehow cannot access camera from where they are started, but i have no clue why and thats why i ask for help, any comment on this would be helpful.
I'm not exactly sure why it fails at this stage already, but even if it worked, I doubt it is possible to then connect to this camera from a client. The reason is that there is a split between local (logged in users) and global (kernel, services, etc.) namespace when it comes to shared memory (which is what the OBS virtual camera uses), see also https://docs.microsoft.com/en-us/windows/win32/termserv/kernel-object-namespaces. I think services always create in the global namespace, but logged in users always under the local one, except if they override this behavior. Since in the context of OBS it doesn't make sense that the virtual camera data comes from somewhere that is not the user session (like a service), the OBS camera device would never try to access the global namespace. I have a feeling this is a dead end. You should see the same issue with the Unity Capture backend, but it may be worth a try.
Thing that bothers me most is that opencv can read from camera while being a windows service, but we can't send image back, this is sad ;(
I tried with Unity backend, and it's is even more disturbing. In logs i see that there were frames sent, I print out "frame sent" in while loop, but image on preview is not changing. Almost same situation, standalone version works, service version dont, but this time there's no error. Anyway thank you for quick reply, I guess I'll have to stick to autolaunch script and no-console mode while compiling exe.
Thanks for trying out Unity Capture as well. I'll close this issue since there isn't anything I can do here, but if you or someone else finds a better solution, please comment.