Now we can save video by right-click
This commit is contained in:
		
							parent
							
								
									0026885730
								
							
						
					
					
						commit
						fe7e4d5a11
					
				@ -6,6 +6,7 @@ import fastapi
 | 
			
		||||
import uvicorn
 | 
			
		||||
from PIL import Image
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HTML = """
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
@ -13,10 +14,11 @@ HTML = """
 | 
			
		||||
    <title>MuJoCo maze visualizer</title>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <h2>MuJoCo Maze Visualizer</h2>
 | 
			
		||||
    <script>
 | 
			
		||||
      var web_socket = new WebSocket('ws://127.0.0.1:{{port}}/ws');
 | 
			
		||||
      web_socket.binaryType = "arraybuffer";
 | 
			
		||||
      web_socket.onmessage = function(event) {
 | 
			
		||||
      var ws_image = new WebSocket('ws://127.0.0.1:{{port}}/ws');
 | 
			
		||||
      ws_image.binaryType = "arraybuffer";
 | 
			
		||||
      ws_image.onmessage = function(event) {
 | 
			
		||||
          var canvas = document.getElementById('canvas');
 | 
			
		||||
          var ctx = canvas.getContext('2d');
 | 
			
		||||
          var blob = new Blob([event.data], {type:'image/png'});
 | 
			
		||||
@ -28,10 +30,20 @@ HTML = """
 | 
			
		||||
          console.log(url);
 | 
			
		||||
          image.src = url;
 | 
			
		||||
      }
 | 
			
		||||
      function saveVideo() {
 | 
			
		||||
          var xhr = new XMLHttpRequest();
 | 
			
		||||
          xhr.open('GET', 'https://via.placeholder.com/150', true);
 | 
			
		||||
          xhr.responseType = 'blob';
 | 
			
		||||
          xhr.onerror = err => {
 | 
			
		||||
              alert('Video is not ready');
 | 
			
		||||
          };
 | 
			
		||||
          xhr.send();
 | 
			
		||||
       }
 | 
			
		||||
    </script>
 | 
			
		||||
    <div>
 | 
			
		||||
      <canvas id="canvas" width="600" height="480"></canvas>
 | 
			
		||||
    </div>
 | 
			
		||||
    <a href="video">Video</a>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
"""
 | 
			
		||||
@ -42,6 +54,7 @@ class _ServerWorker(mp.Process):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.pipe = pipe
 | 
			
		||||
        self.port = port
 | 
			
		||||
        self.video_frames = []
 | 
			
		||||
 | 
			
		||||
    def _run_server(self) -> None:
 | 
			
		||||
 | 
			
		||||
@ -49,19 +62,20 @@ class _ServerWorker(mp.Process):
 | 
			
		||||
        html = HTML.replace("{{port}}", str(self.port))
 | 
			
		||||
 | 
			
		||||
        @app.get("/")
 | 
			
		||||
        async def get():
 | 
			
		||||
        async def root():
 | 
			
		||||
            return fastapi.responses.HTMLResponse(html)
 | 
			
		||||
 | 
			
		||||
        server = None
 | 
			
		||||
 | 
			
		||||
        @app.websocket("/ws")
 | 
			
		||||
        async def ws_send_image(websocket: fastapi.WebSocket):
 | 
			
		||||
        async def ws(websocket: fastapi.WebSocket):
 | 
			
		||||
            await websocket.accept()
 | 
			
		||||
            loop = asyncio.get_running_loop()
 | 
			
		||||
            while True:
 | 
			
		||||
                image_array = await loop.run_in_executor(None, self.pipe.recv)
 | 
			
		||||
                if image_array is None:
 | 
			
		||||
                    break
 | 
			
		||||
                self.video_frames.append(image_array)
 | 
			
		||||
                image = Image.fromarray(image_array)
 | 
			
		||||
                with io.BytesIO() as stream:
 | 
			
		||||
                    image.save(stream, format="png")
 | 
			
		||||
@ -70,6 +84,17 @@ class _ServerWorker(mp.Process):
 | 
			
		||||
            await websocket.close()
 | 
			
		||||
            server.should_exit = True
 | 
			
		||||
 | 
			
		||||
        @app.get("/video")
 | 
			
		||||
        async def video():
 | 
			
		||||
            import imageio
 | 
			
		||||
 | 
			
		||||
            writer = imageio.get_writer("/tmp/mujoco-maze-video.mp4")
 | 
			
		||||
            for frame in self.video_frames:
 | 
			
		||||
                writer.append_data(frame)
 | 
			
		||||
            writer.close()
 | 
			
		||||
            video = open("/tmp/mujoco-maze-video.mp4", mode="rb")
 | 
			
		||||
            return fastapi.responses.StreamingResponse(video, media_type="video/mp4")
 | 
			
		||||
 | 
			
		||||
        config = uvicorn.Config(app, port=self.port)
 | 
			
		||||
        server = uvicorn.Server(config)
 | 
			
		||||
        server.run()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user