본문 바로가기
Back-end/JAVA & Spring

[ffmpeg] 동영상 초마다 이미지 변환 command line + java code

by 꼬바리 2021. 12. 14.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;

public class cutVideo {
	public static void main(String[] args) throws IOException {
		String path = "C:/case_3/p_1/123.avi";
		File f = new File(path);
		
		if (f.exists()) {
			String result = convert();
			System.out.println("result : "+result);
		}
	}
	
	public static String convert() throws IOException {
		String ffmpegPath = "C:/ffmpeg/ffmpeg-4.4.1-full_build/bin/ffmpeg";   // 예) /work/ffmpeg
		String originVideoPath = "C:/case_3/p_1/123.avi"; 
		String onlyPath = originVideoPath.substring(0,originVideoPath.lastIndexOf("/")+1);
        String onlyFileName = originVideoPath.substring(originVideoPath.lastIndexOf("/")+1,originVideoPath.lastIndexOf("."));

		File source = new File(originVideoPath);
		FFmpegFrameGrabber streamGrabber = FFmpegFrameGrabber.createDefault(source);
        streamGrabber.start();
        int width = streamGrabber.getImageWidth();
    	int height = streamGrabber.getImageHeight();
        int bitrate = streamGrabber.getVideoBitrate()/1000;
        int frame = (int) streamGrabber.getVideoFrameRate();
        System.out.println("vidoe width : "+ width);
        System.out.println("vidoe height : "+ height);
        System.out.println("vidoe bitrate : "+ bitrate + "k");
        System.out.println("vidoe frame : "+ frame);

        List<String> commands = new ArrayList<String>();
        commands.add(ffmpegPath);
        commands.add("-i");
        commands.add(originVideoPath);
        commands.add("-ss");
        commands.add("00:00:01");
        commands.add("-vf");
        commands.add("thumbnail="+frame);
        commands.add("-vsync");
        commands.add("0");
        commands.add(onlyPath+onlyFileName+"_%04d.jpg");

		// 프로세스 속성을 관리하는 ProcessBuilder 생성.
		ProcessBuilder pb = new ProcessBuilder(commands);
		pb.redirectErrorStream(true);
		Process p = null;
		 try { 
		        // 프로세스 작업을 실행
		        p = pb.start();
		} catch (Exception e) {         
		     e.printStackTrace();

		     p.destroy();
		     return null;
		}

		exhaustInputStream(p.getInputStream());   // 자식 프로세스에서 발생되는 inputstrem를 소비시켜야합니다.

		  try {
		        // p의 자식 프로세스의 작업이 완료될 동안 p를 대기시킴
		        p.waitFor();
		 } catch (InterruptedException e) {
		         p.destroy();
		 }

		// 정상 종료가 되지 않았을 경우
		 if (p.exitValue() != 0) {
		       System.out.println("변환 중 에러 발생");
		       return null;
		 }

		  p.destroy();
		  return "성공";
		}

	private static void exhaustInputStream(final InputStream is) {
		// InputStream.read() 에서 블럭상태에 빠지기 때문에 따로 쓰레드를 구현하여 스트림을 소비한다
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String cmd = null;
			while ((cmd = br.readLine()) != null) { // 읽어들일 라인이 없을때까지 계속 반복
				System.out.println(cmd);
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}




	
}

FFmpegFrameGrabber 라이브러리로 해당 영상의 정보를 가져온다.

메이븐은 블로그에 있으니 참고

 

ffmpeg 커맨드 라인에 -ss 는 시작 시점을 정해준것

 

ffmpeg 프로그램 다운받고 해당 경로 넣어준다.

위 코드 실행시,

동영상의 1초마다 이미지 변환되어 저장된다

 

이코드를 짠 이유는 AI 학습을 위해서

CCTV분석은 머신러닝학습시 영상을 통채로 학습하는게 아니라 영상을 모든 프레임 혹은 초마다 잘라서

학습..한다..

 

 

728x90
반응형

댓글