Java에서 FFmpeg를 활용한 로컬 영상 RTSP 스트리밍 구현

준비사항

  • FFmpeg: 멀티미디어 처리 오픈소스 도구 (권장 버전: 4.2 이상) - 공식 사이트에서 다운로드
  • EasyDarwin: RTSP 미디어 서버 (테스트용) - easydarwin.org에서 릴리즈 바이너리 획득
  • VLC 미디어 플레이어: 스트림 재생 확인용

FFmpeg 명령어 구조

로컬 영상을 RTSP 프로토콜로 전송하는 기본 명령어:

ffmpeg -re -i [입력경로] -f rtsp rtsp://[서버주소]/[스트림명]

각 옵션 설명:

  • -re: 입력 파일의 프레임레이트로 읽기 (스트리밍 시 필수)
  • -i: 입력 소스 지정
  • -f rtsp: 출력 포맷을 RTSP로 설정

Java 구현 코드

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class RtspStreamer {
    
    private Process streamingProcess;
    private final String ffmpegHome;
    private final String mediaRoot;
    private final String serverUrl;
    
    public RtspStreamer(String ffmpegHome, String mediaRoot, String serverUrl) {
        this.ffmpegHome = ffmpegHome;
        this.mediaRoot = mediaRoot;
        this.serverUrl = serverUrl;
    }
    
    public boolean startStream(String channelId, String mediaFile) {
        terminateExistingStream();
        
        StringBuilder cmdBuilder = new StringBuilder();
        cmdBuilder.append(ffmpegHome).append("/ffmpeg ");
        cmdBuilder.append("-re ");                    // 프레임레이트 동기화
        cmdBuilder.append("-i ").append(mediaRoot)   // 입력 파일
                   .append("/").append(channelId)
                   .append("/").append(mediaFile).append(" ");
        cmdBuilder.append("-f rtsp ").append(serverUrl); // RTSP 출력
        
        String fullCommand = cmdBuilder.toString();
        System.out.println("[실행 명령] " + fullCommand);
        
        try {
            streamingProcess = Runtime.getRuntime().exec(fullCommand);
            
            // FFmpeg의 표준에러 스트림을 읽어 로깅
            Thread loggerThread = new Thread(() -> {
                try (BufferedReader errReader = new BufferedReader(
                        new InputStreamReader(streamingProcess.getErrorStream()))) {
                    String logLine;
                    while ((logLine = errReader.readLine()) != null) {
                        System.out.println("[FFmpeg] " + logLine);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
            loggerThread.setDaemon(true);
            loggerThread.start();
            
            // 프로세스 종료 대기 (0이면 정상 종료)
            int exitCode = streamingProcess.waitFor();
            return exitCode == 0;
            
        } catch (Exception ex) {
            System.err.println("스트리밍 시작 실패: " + ex.getMessage());
            return false;
        }
    }
    
    public void stopStream() {
        terminateExistingStream();
    }
    
    private void terminateExistingStream() {
        if (streamingProcess != null && streamingProcess.isAlive()) {
            System.out.println("[정보] 기존 스트림 종료");
            streamingProcess.destroy();
            streamingProcess = null;
        }
    }
}

사용 예시

public class Main {
    public static void main(String[] args) {
        RtspStreamer streamer = new RtspStreamer(
            "E:/tools/ffmpeg/bin",           // FFmpeg 경로
            "E:/media/videos",                 // 영상 저장 경로
            "rtsp://127.0.0.1:554/live/stream" // RTSP 서버 주소
        );
        
        // 채널 "cam01"의 "sample.mp4" 스트리밍 시작
        boolean result = streamer.startStream("cam01", "sample.mp4");
        System.out.println("스트리밍 상태: " + (result ? "성공" : "실패"));
    }
}

동작 확인 방법

  1. EasyDarwin 실행 후 http://127.0.0.1:10008 접속
  2. Java 프로그램 실행하여 스트림 푸시
  3. EasyDarwin 웹 인터페이스에서 푸시/풀 스트림 상태 확인
  4. VLC에서 미디어 → 네트워크 스트림 열기 선택 후 RTSP URL 입력하여 재생

주의사항

  • FFmpeg 바이너리 경로는 환경에 맞게 수정 필요
  • 프로세스 종료 시 destroy() 호출로 자원 정리
  • 에러 스트림 처리 스레드를 분리하여 블로킹 방지
  • 운영 환경에서는 ProcessBuilder 사용 권장

태그: ffmpeg rtsp java EasyDarwin 미디어스트리밍

6월 10일 19:14에 게시됨