User Tools

Site Tools


rocnet:cam-fr

Diffusion par caméra

Demos

Python

Script Python

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming
 
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
 
PAGE="""\
<html>
<head>
<title>V200 Camera</title>
</head>
<body>
<img src="stream.mjpg" width="320" height="240">
</body>
</html>
"""
 
class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()
 
    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)
 
class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()
 
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True
 
with picamera.PiCamera(resolution='320x240', framerate=12) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8081)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

Démarrer le script avec:

python3 cam.py

Cela utilise environ 5% du processeur sur un RPi 4+.

Ouvrir l'URL dans le navigateur avec:

http://raspberry:8081

Où <raspberry> doit être le nom d'hôte ou l'adresse IP du Raspberry Pi sur lequel le script Python tourne.

Sortie du serveur WEB Python

<html>
<head>
<title>V200 Camera</title>
</head>
<body>
<img src="stream.mjpg" width="320" height="240">
</body>
</html>


Visionneuses

Texte

Pour activer la diffusion MJPEG dans un objet texte, Le contenu du texte doit être défini à:

mjpg:<host>:<port>

Par exemple:

mjpg:192.168.100.167:8081

Manette de locomotive

Définir la caméra hôte et le port dans l'onglet Interface des propriétés de la locomotive.

Liens

Solutions IE

MS IE ne supporte pas la diffusion de vidéo mjpg.


Scission

    00000130: 55 E6 9D 09 E3 78 60 4E 31 81 BB 05 94 12 A3 38 |U....x`N1......8|
    00000140: 27 6B 74 23 D3 03 35 B5 2E 6E 58 B6 BF AD 46 D3 |'kt#..5..nX...F.|
    00000150: B6 FB 7E 07 FF D9 0D 0A 2D 2D 46 52 41 4D 45 0D |..~.....--FRAME.|
    00000160: 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 3A 20 69 |.Content-Type: i|
    00000170: 6D 61 67 65 2F 6A 70 65 67 0D 0A 43 6F 6E 74 65 |mage/jpeg..Conte|
    00000180: 6E 74 2D 4C 65 6E 67 74 68 3A 20 31 32 35 32 34 |nt-Length: 12524|
    00000190: 33 0D 0A 0D 0A FF D8 FF DB 00 84 00 01 01 01 01 |3...............|
    000001A0: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
    000001B0: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 02 02 |................|
    
    
    00000120: 8D B9 66 EE EF AD 96 DD 74 E4 76 DF FA 63 FA AD |..f.....t.v..c..|
    00000130: 29 2D 62 AD A6 AA FA FC B9 B4 F9 9F FF D9 0D 0A |)-b.............|
    00000140: 2D 2D 46 52 41 4D 45 0D 0A 43 6F 6E 74 65 6E 74 |--FRAME..Content|
    00000150: 2D 54 79 70 65 3A 20 69 6D 61 67 65 2F 6A 70 65 |-Type: image/jpe|
    00000160: 67 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 |g..Content-Lengt|
    00000170: 68 3A 20 34 37 30 37 37 0D 0A 0D 0A FF D8 FF DB |h: 47077........|
    00000180: 00 84 00 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
    00000190: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
    000001A0: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|

Source: https://stackoverflow.com/questions/21702477/how-to-parse-mjpeg-http-stream-from-ip-camera

import cv2
import urllib 
import numpy as np
 
stream = urllib.urlopen('http://localhost:8080/frame.mjpg')
bytes = ''
while True:
    bytes += stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)   
rocnet/cam-fr.txt · Last modified: 2019/08/28 10:50 by phil45