SpringBoot 및 FFMPEG를 사용하여 비디오 트랜스코더를 구축하는 방법!

최근에 감시 카메라 시스템 작업을 시작했는데 수집된 비디오를 웹 페이지에 표시할 수 있기를 원합니다.
언뜻 보기에는 매우 쉬울 것 같았지만 곧 머리를 숙여야 한다는 것을 깨달았습니다!

어떻게 작동해야 합니까?



카메라는 구성 정보 및 비디오 스트림을 검색할 수 있는 API가 있는 NVR(숫자 비디오 레코더)에 연결됩니다. 웹에서 조금 찾아보니(예, 문서에 접근하기 어렵습니다..) NVR에서 사용하는 통신 프로토콜이 RTSP(Real-Time Streaming Protocol)라는 것을 알게 되었습니다. 이것이 내가 주요 문제에 직면하는 곳입니다! 이 프로토콜을 지원하지 않는 HTML 페이지에서 어떻게 사용합니까? 내 솔루션은 동영상을 더 잘 알려진 형식(MP4)과 초표준 프로토콜(Http)로 트랜스코딩할 수 있는 서버를 사용하는 것입니다. 이렇게 하면 내 서버를 프록시로 사용하여 카메라에 대한 액세스 식별자를 숨길 수도 있습니다.


그럼 어떻게 해야 할까요?



비디오 변환을 수행하는 것으로 잘 알려진 훌륭한 도구는 FFMPeg이므로 이를 사용하여 RSTP를 변환하는 방법을 알아보기 시작했습니다. 작동하는 명령줄을 빠르게 찾습니다.

ffmpeg -y -loglevel level+info -n -re -acodec pcm_s16le -rtsp_transport tcp -i rtsp://user:[email protected]:554/ISAPI/Streaming/channels/101/live -vcodec copy -af asetrate=22050 -acodec aac -b:a 96k -nostdin myvideo.mp4


그렇다면 SpringBoot로 프록시를 만드는 방법은 무엇입니까? 실제로 매우 간단합니다. StreamingResponseBody 개체를 사용하기만 하면 됩니다. 이를 통해 애플리케이션이 나머지 API를 차단하지 않고 응답 출력 스트림에 직접 쓸 수 있는 비동기 요청 처리를 반환할 수 있습니다.

마지막으로 컨트롤러에서 FFMPEG를 사용하여 API를 통해 스트림을 전송하기만 하면 됩니다. "Runtime.getRuntime().exec("ffmpeg...) "를 사용할 수 있었지만 내 스트림을 가져오는 방법을 알 수 없었습니다. 다행스럽게도 매직 라이브러리Jaffree를 찾았습니다. "Jaffree는 JAva FFmpeg 및 FFprobe 무료 명령줄 래퍼. Jaffree는 프로그래밍 방식의 비디오 제작 및 소비를 지원합니다(투명성 포함)."

해결책



다음은 HTML 페이지에서 형식을 사용할 수 있도록 HikVision 카메라에서 비디오 스트림을 릴레이하는 최종 솔루션 및 방법입니다.

import com.github.kokorin.jaffree.StreamType;
import com.github.kokorin.jaffree.ffmpeg.FFmpeg;
import com.github.kokorin.jaffree.ffmpeg.PipeOutput;

@RestController
@RequestMapping("/video")
@Log4j2
public class VideoController {
    @GetMapping(value = "/live.mp4")
    @ResponseBody
    public ResponseEntity<StreamingResponseBody> livestream(@PathVariable("id") Long tipperId) throws Exception {

        String rtspUrl = "rtsp://user:[email protected]:554/ISAPI/Streaming/channels/101/live";

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(os -> {
                    FFmpeg.atPath()
                            .addArgument("-re")
                            .addArguments("-acodec", "pcm_s16le")
                            .addArguments("-rtsp_transport", "tcp")
                            .addArguments("-i", rtspUrl)
                            .addArguments("-vcodec", "copy")
                            .addArguments("-af", "asetrate=22050")
                            .addArguments("-acodec", "aac")
                            .addArguments("-b:a", "96k" )
                            .addOutput(PipeOutput.pumpTo(os)
                                    .disableStream(StreamType.AUDIO)
                                    .disableStream(StreamType.SUBTITLE)
                                    .disableStream(StreamType.DATA)
                                    .setFrameCount(StreamType.VIDEO, 100L)
                                     //1 frame every 10 seconds
                                    .setFrameRate(0.1)
                                    .setDuration(1, TimeUnit.HOURS)
                                    .setFormat("ismv"))
                            .addArgument("-nostdin")
                            .execute();
                });

    }
}


또한 비동기 요청에 대한 제한 시간을 늘리려면 SpringBoot 애플리케이션(application.properties 파일)의 구성을 수정해야 합니다.

spring.mvc.async.request-timeout = 3600000


웹 페이지에서 API를 호출하기만 하면 됩니다.

<div class="video">
  <video width="100%" height="auto" controls autoplay muted loop *ngIf="event?.video">
    <source src="http://localhost:8080/video/live.mp4"
            type="video/mp4">
    Sorry, your browser doesn't support embedded videos.
  </video>
</div>


결과를 확인하십시오.



그게 다야!

좋은 웹페이지 즐겨찾기