Saltar al contenido

Cómo enviar una transmisión de video HTTP a cualquier cantidad de clientes a través de un servidor web Spring

Solución:

No estoy seguro de qué tipo de fuente está utilizando para generar su transmisión de video (cámara en vivo o un archivo de video o video de youtube o ..)

Probablemente pueda usar StreamingResponseBody (requiere Spring 4.2+). Consulte los siguientes enlaces

http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/streaming-response-body/

http://shazsterblog.blogspot.in/2016/02/asynchronous-streaming-request.html

Prueba esto –

    @GetMapping("/stream1")
        @ResponseBody
        public StreamingResponseBody getVidoeStream1(@RequestParam String any) throws IOException {
            /* do security check before connecting to stream hosting server */ 
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<Resource> responseEntity = restTemplate.exchange( "http://localhost:8080/stream", HttpMethod.GET, null, Resource.class );
            InputStream st = responseEntity.getBody().getInputStream();
            return (os) -> {
                readAndWrite(st, os);
            };


    }

private void readAndWrite(final InputStream is, OutputStream os)
            throws IOException {
        byte[] data = new byte[2048];
        int read = 0;
        while ((read = is.read(data)) > 0) {
            os.write(data, 0, read);
        }
        os.flush();
    }

Deberia de funcionar. Puede escribir su propia implementación de readAndWrite () según sus requisitos.

Entonces, su controlador de proxy de primavera podría ser algo como esto …

@Controller
public class HttpStreamProxyController {

    @RequestMapping("https://foroayuda.es/spring") 
    @ResponseBody
    public StreamingResponseBody  getSecuredHttpStream() {
       if (clientIsSecured) {
       //... Security information

    RestTemplate restTemplate = new RestTemplate();
    // get video stream by connecting to stream hosting server  like this
            ResponseEntity<Resource> responseEntity = restTemplate.exchange( "https://ur-to-stream", HttpMethod.GET, null, Resource.class );
            InputStream st = responseEntity.getBody().getInputStream();
    // Or if there is any other preferred way of getting the video stream use that. The idea is to get the video input stream    

    // now return a StreamingResponseBody  object created by following lambda 
            return (os) -> {
                readAndWrite(st, os);
            };

       } else {
          return null;
       }

   }
}

El StreamingResponseBody devuelto por su punto final de descanso funcionará bien con HTML5, que podría ser algo así como …

<video width="320" height="240" controls>
  <source src="https://foroayuda.es/spring" type="video/mp4">
  Your browser does not support the video tag
</video>

Luché con este mismo problema durante días, intentando migrar mi aplicación de nodo a Spring / React. Estoy usando una raspberry pi que ejecuta Motion, que actúa como un servidor de transmisión remoto que antes podía usar el módulo de nodo mjpeg-proxy para proxy fácilmente de la manera que OP desee. Este hilo fue el conjunto de ejemplos más útil en mi búsqueda para hacer esto en Java, sin embargo, ninguno de los ejemplos funcionó para mí. Espero que mi clase de controlador y mi componente ayuden a otros a intentar lo mismo.

Por favor tome nota de response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString"); como el boundary=BoundaryString porción fue la última pieza crítica. Abrí el depurador de Chrome mientras me conectaba directamente a la transmisión y esto estaba en los encabezados de respuesta; cuando lo copié, ¡de repente todo funcionó!


import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.net.URI;

@RestController
@RequestMapping(value = "/video")
public class VideoController {

    Logger log = LoggerFactory.getLogger(VideoController.class);

    @RequestMapping("/oculus")
    public void oculus(HttpServletResponse response) {
        log.info("Calling /video/oculus...");
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.execute(
                URI.create("http://oculus:8081"),
                HttpMethod.GET,
                (ClientHttpRequest request) -> {},
                responseExtractor -> {
                    response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString");
                    IOUtils.copy(responseExtractor.getBody(), response.getOutputStream());
                    return null;
                }
        );
    }

    @RequestMapping("/door")
    public void door(HttpServletResponse response) {
        log.info("Calling /video/door...");

        RestTemplate restTemplate = new RestTemplate();
        restTemplate.execute(
                URI.create("http://vox:9002"),
                HttpMethod.GET,
                clientHttpRequest -> {
                    clientHttpRequest.getHeaders().add(HttpHeaders.AUTHORIZATION, "Basic blahblahBase64encodedUserAndPass=");
                },
                responseExtractor -> {
                    response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString");
                    IOUtils.copy(responseExtractor.getBody(), response.getOutputStream());
                    return null;
                }
        );
    }

}

He incluido ejemplos para usar la autenticación básica de Motion, así como una transmisión desprotegida.

Ambas transmisiones están disponibles en mi aplicación usando el siguiente bit de react js


class Video extends React.Component{
    render() {
        return (
            <div className="Content">
                <p>
                    <img className="stream" src="https://foroayuda.es/video/oculus"/>
                </p>
                <p>
                    <img className="stream" src="/video/door"/>
                </p>
            </div>
        );
    }
}

export default Video;```

Una buena manera de hacer transmisión de video en una aplicación Spring Boot (sin embargo, usé una fuente diferente: una cámara USB):

@GetMapping(value = "/stream")
public ResponseEntity<StreamingResponseBody> stream() {
    StreamingResponseBody stream = outputStream -> {
        while (streaming.get()) {
            final var raw = streamImage.get();
            final var jpeg = convert(byte2Buffered(raw.getImageData(), raw.getImageWidth(), raw.getImageHeight()));
            outputStream.write(jpeg);
        }
        outputStream.flush();
    };
    final var headers = new HttpHeaders();
    headers.add("Access-Control-Allow-Origin", "*");
    headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
    headers.add("Content-Type", "multipart/x-mixed-replace;boundary=frame");
    headers.add("Expires", "0");
    headers.add("Pragma", "no-cache");
    headers.add("Max-Age", "0");
    return ResponseEntity.ok()
            .headers(headers)
            .body(stream);
}

De esta manera, obtendrá una transmisión en el punto final de la URL, que puede incrustar en una página web usando img Etiqueta HTML.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *