I believe you're correct, you can't access the device with 2 separate programs at once. That said, you can certainly record and view with some careful programming (my choice would be Flask web server in Python).
A quicker approach would be to use the motion and motioneye packages with the output_all enabled. You can even download a distribution ready to go to test it:
https://github.com/ccrisan/motioneyeos
output_all
Type: Boolean Range / Valid values: on, off Default: off Option Topic
Picture are saved continuously as if motion was detected all the time.
This feature is not meant to be the normal mode of operation.
Especially not if you have the output_normal or output_motion features
enabled since it will keep on saving pictures on the disk and you will
soon run out of disk space. So be careful with this command.
If your frame rate is 10 pictures per second motion will save 10 new
picture pr second until the disk is full.
It does all the normal actions that are done when motion is detected.
It saves pictures on the harddisk, execute external scripts, etc as
fast as the frame rate of the camera. So it is probably a good idea to
run with a low framerate when using this feature and to not use
activate all the features that saves files on the disk.
The idea of this feature is that you can turn the feature on and off
for a short period of time to test or to generate continuous mpeg
films when needed.