2014-10-12 13 views
1

xuggler를 사용하여 BufferedImages 목록에서 비디오를 만들려고합니다. 나는 튜토리얼 this을 따라 갔고 코드는 완벽하게 작동합니다.xuggler를 사용하여 BufferedImages를 비디오에 결합

java.lang.RuntimeException가 : 패킷을 쓰지 못했습니다 : 내 코드 예제에서 작업 코드를 통합 할 때

그러나, 나는 RuntimeException을 얻을 [email protected]을 [완료 : true, dts : 67915, pts : 67915, 크기 : 24201, 키 : false, 플래그 : 0, 스트림 인덱스 : 0, 지속 시간 : 1, 위치 : -1, 시간 기준 : 1/65535] at com .xuggle.mediatool.MediaWriter.writePacket (MediaWriter.java:1215) at com.xuggle.mediatool.MediaWriter.encodeVideo (MediaWriter.java:767) at com.xuggle.mediatool.MediaWriter.encodeVideo (MediaWriter.java:810)) at s3.S3CompositeUtil.generateVideo (S3Composite s3.S3CompositeUtil.main에서 Util.java:247) (S3CompositeUtil.java:349)

Xuggler 문서가 있음을 언급 : 발신자가 지정한 경우 IMediaData.getTimeStamp()는 항상 일정하게 증가 또는되어 있는지 확인해야합니다 RuntimeException이 발생합니다.

그러나 비디오를 생성하는 데 걸리는 시간이 어느 시점에서 감소했다고 생각하지 않습니다.

private void generateVideo() { 
    System.out.println("Creating video..."); 
    String outputMoviePath = ""; 
    IMediaWriter writer = null; 
    if (allLabels) { 
     outputMoviePath = TEMP_DIR_PATH + "/" + clipName + "/" + clipName + "_" + "all_labels" + ".avi"; 
    } 
    else { 
     outputMoviePath = TEMP_DIR_PATH + "/" + clipName + "/" + clipName + "_" + labels[desiredLabelIdx] + ".avi"; 
    } 
    writer = ToolFactory.makeWriter(outputMoviePath); 
    // add one video stream, with position 0 and ID 0, and a frame rate of OUTPUT_MOVIE_FPS 
    writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4, vidWidth, vidHeight); 
    long startTime = System.nanoTime(); 
    for (int idxF = 0; idxF < numFrames; idxF++) { 
     BufferedImage currFrameImg = convertToType(videoBIHolder.get(idxF), BufferedImage.TYPE_3BYTE_BGR); 
//   BufferedImage currFrameImg = videoBIHolder.get(idxF); 
     System.out.println("currFrameImg type is " + currFrameImg.getType()); // debug 
     // encode video to stream at 0 
     long frameTimeInVideo = System.nanoTime() - startTime; 
     System.out.println("Time: " + frameTimeInVideo); 
     writer.encodeVideo(0, currFrameImg, frameTimeInVideo, TimeUnit.NANOSECONDS); 
     // sleep for millisec. amount of time of the frame rate 
     try { 
      Thread.sleep((long) (1000/OUTPUT_MOVIE_FPS)); //OUTPUT_MOVIE_FPS 
     } 
     catch (InterruptedException e) { 
      System.err.println(); 
     } 
    } 

(S3CompositeUtil.java:247가) 나는 OUTPUT_MOVIE_FPS 1 일 필요 라인

  writer.encodeVideo(0, currFrameImg, frameTimeInVideo, TimeUnit.NANOSECONDS); 

하지만 이상한 것은 그것이 5 때, 비디오가 예외없이 만든 것입니다, 2 인 경우 "비디오"는 첫 번째 프레임 (다른 프레임 없음)이고 1 일 때이 예외가 발생합니다.

의견이 있으십니까? 내가 얻을 수있는 모든 도움에 정말로 감사 할 것입니다!

답변

0

나는 멀티미디어 수업 중 하나에서 Xuggler를 가르치고 있으며, 학생들 중 일부는 그림 슬라이드 쇼를 만드는 스톱 모션 애니메이션이나 비디오를 만들 때 유사한 문제를보고했습니다.

우리는 적어도 2 또는 심지어 10 FPS를 만들었습니다. 재미있는 점은 비디오를 저장하는 데 훨씬 많은 메모리를 사용하지 않을 가능성이 높다는 것입니다. MPG4 인코더는 완전히 새로운 프레임이 삽입 될 때까지 프레임에 차이가 없으므로 기본적으로 비어있는 예측 프레임 만 비디오 파일에 삽입 할만큼 충분히 똑똑합니다.

이 접근법의 유일한 단점은 약간 더 많은 인코딩 오버 헤드가 발생한다는 것입니다. 비디오 스트림에 임의의 프레임을 삽입하는 것은 최종적으로 디코더가 빈 예측 프레임 만 삽입 할 수 있다고 결정하더라도 CPU로드를 유발할 것이다.

편집 : 실제로 프레임을 비디오에 25fps의 속도로 삽입하는 것으로 나타났습니다. 위에서 설명한 모든 단점이 있습니다. 그러나 호기심에서 나는 10 fps와 25 fps 사이의 프레임 속도로 테스트를 수행했으며 파일 크기에는 큰 변화가 없음이 밝혀졌습니다. 재미있게도 10fps의 테스트 파일이 가장 큰 파일입니다.

정지 영상의 5 초 풀 HD 비디오는 450kb ~ 580kb 영역에 있습니다. 그래서 프레임 속도를 실험 해보고 가장 낮은 ffmpeg/Xuggler가 H264에 대해 처리 할 수있는 가장 낮은 것을 선택하십시오. (실제로 이것은 어딘가의 문서에 있어야하지만 지금은 찾을 수 없습니다.)

테스트를 위해 동일한 BufferedImage를 다시 삽입하는 다음 코드를 사용했습니다.

final IMediaWriter writer = ToolFactory.makeWriter(outputFile); 
    writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, img.getSize().width, screenshot.getSize().height); 
    long startTime = System.nanoTime(); 
    for (int i=0; i<seconds*25; i++) { 
     BufferedImage bgrScreen = Tools.convertToType(img, BufferedImage.TYPE_3BYTE_BGR); 
     writer.encodeVideo(0, bgrScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); 
     try { 
      Thread.sleep((long) (1000/25)); 
     } catch (InterruptedException e) { 
      // ignore 
     } 
    } 
    writer.close(); 

프로 팁 : 우리는 우리가 정확한 프레임을 칠 것을 우리가 확인 할 수 있도록 인코딩 (writer.encodeVideo)를 수행하기 위해 이미지 프레임을 제공하는 하나 개의 스레드를 사용하여 하나 개의 스레드가 실제 애플리케이션에서 25fps의 속도. 귀하의 예제 (또한 내 테스트 코드에서) Xuggler/ffmpeg의 인코딩 시간이 추가됩니다.

+0

답변 해 주셔서 감사합니다. 내가 2 FPS를했을 때, 총 12 프레임이 있긴하지만 처음 프레임의 "비디오"만 얻었습니다. 따라서 약 6 초 동안 그 이미지를 거의 보여주었습니다. 그 일이 당신이나 당신의 학생들에게 일어 났습니까? 그렇다면 어떻게 그 문제를 해결 했습니까? – labananala

+0

안녕하세요, 그래, 우리는 비슷한 효과를 경험했지만 지금은 언제 어떻게 어떻게 발생했는지 기억하기가 어렵습니다. 그럼에도 불구하고 지금은 10fps에서 25fps의 프레임 속도로 단일 스틸 이미지 인코딩을 시도하고 그 결과를 제 대답에 추가했습니다. 아마도 이것은 프레임 속도를 올리도록 설득 할 수 있습니다. –

+0

알았어, 조언 주셔서 감사합니다! 결국 프레임 속도를 5로 올린 다음 각 프레임을 여러 번 추가하여 비디오의 프레임 속도가 1로 표시되도록했습니다. – labananala