arendst / Tasmota

Alternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at
https://tasmota.github.io/docs
GNU General Public License v3.0
21.97k stars 4.77k forks source link

tasmota-webcam xdrv_81_webcam.ino stream should start with boundary marker #12376

Closed mnsuk closed 3 years ago

mnsuk commented 3 years ago

PROBLEM DESCRIPTION

A clear and concise description of what the problem is. I am attempting to process the mjpeg stream produced by tasmota-webcam. I have use two different client libraries and both report that boundary string is missing. e.g from py-mjpeg: mjpeg.ProtoError: Boundary string expected, but not found. Looking at the code in xdrv_81_webcam.ino and confirming by examining the HTTP headers and content in python debug shows that the boundary string is sent after each jpeg frame. E.g. the following is sent:

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace;boundary=e8b8c539-047d-4777-a985-fbba6edff11e
Content-Type: image/jpeg
Content-Length: 17281
…….(image content)
—e8b8c539-047d-4777-a985-fbba6edff11e
Content-Type: image/jpeg
Content-Length: 17291
……..(image content)
—e8b8c539-047d-4777-a985-fbba6edff11e

So after the headers the content goes straight to the first jpeg image headers, then a boundary, then repeats for each image. I believe that the boundary should have been sent prior to the first jpeg image too (certainly that is what expected by the source for the python libraries I looked at). In summary the sequence should be:

headers boundary image boundary image boundary image etc

whereas it is:

headers image boundary image boundary etc

REQUESTED INFORMATION

Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!

- [ ] If using rules, provide the output of this command: `Backlog Rule1; Rule2; Rule3`:
```lua
  Rules output here:
- [ ] Set `weblog` to 4 and then, when you experience your issue, provide the output of the Console log:
```lua
  Console output here:
n/a

TO REPRODUCE

Steps to reproduce the behavior: Flash an ESP32 cam with tasmota-webcam. Attempt to process resultant mjpeg stream with py-mjpeg client code. (Using this library is just an easy example to reproduce, I've tried others that exhibit the same problem with the stream) Using library https://pypi.org/project/py-mjpeg/

from mjpeg.client import MJPEGClient

url='http://david:81/cam.mjpeg'

# Create a new client thread
client = MJPEGClient(url)

# Allocate memory buffers for frames
bufs = client.request_buffers(65536, 50)
for b in bufs:
    client.enqueue_buffer(b)

# Start the client in a background thread
client.start()
# grab 4 frames from stream
i = 4
while i > 0:
    buf = client.dequeue_buffer()
    data = memoryview(buf.data)[:buf.used]
    f = open('rat.jpg', 'wb')
    f.write(data)
    f.close()
    client.enqueue_buffer(buf)
    i = i - 4
client.print_stats()

EXPECTED BEHAVIOUR

A clear and concise description of what you expected to happen. stream is processed without error.

SCREENSHOTS

If applicable, add screenshots to help explain your problem.

python3 
Traceback (most recent call last):
  File "/Users/martin/Library/Python/3.7/lib/python/site-packages/mjpeg/client.py", line 151, in run
    self.process_stream(s)
  File "/Users/martin/Library/Python/3.7/lib/python/site-packages/mjpeg/client.py", line 120, in process_stream
    timestamp, clen = read_mjpeg_frame(stream, boundary, mem, length)
  File "/Users/martin/Library/Python/3.7/lib/python/site-packages/mjpeg/__init__.py", line 152, in read_mjpeg_frame
    hdr = read_headers(stream, boundary)
  File "/Users/martin/Library/Python/3.7/lib/python/site-packages/mjpeg/__init__.py", line 38, in read_headers
    raise ProtoError('Boundary string expected, but not found')
mjpeg.ProtoError: Boundary string expected, but not found

ADDITIONAL CONTEXT

Add any other context about the problem here.

(Please, remember to close the issue when the problem has been addressed)

ascillato2 commented 3 years ago

Moving this issue to Ideas. Thanks.