2012-09-28 3 views
3

저는 비디오에서 미리보기 이미지를 생성하기 위해 노력하고 있습니다. 나는 그것을 할 수 있지만 비디오에서 하나의 축소판 이미지 만 필요하지만 비디오의 다른 시간에 하나 이상의 이미지가 있습니다. 축소판을 생성하는 데 다음 코드를 사용했습니다. 비디오의 중간 부분에서 하나의 미리보기 이미지 만 가져 오려면 다음 코드에서 수정해야 할 내용을 제안하십시오. 내가 사용하는 코드는 (내가 Xuggler을 사용했다) 다음과 같습니다동영상에서 하나의 미리보기 이미지 만 캡처하십시오.

import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import com.xuggle.mediatool.IMediaReader; 
import com.xuggle.mediatool.MediaListenerAdapter; 
import com.xuggle.mediatool.ToolFactory; 
import com.xuggle.mediatool.event.IVideoPictureEvent; 
import com.xuggle.xuggler.Global; 

public class Main { 

    public static final double SECONDS_BETWEEN_FRAMES = 10; 
    private static final String inputFilename = "D:\\k\\Knock On Wood Lesson.flv"; 
    private static final String outputFilePrefix = "D:\\pix\\"; 
// The video stream index, used to ensure we display frames from one and 
// only one video stream from the media container. 
    private static int mVideoStreamIndex = -1; 
// Time of last frame write 
    private static long mLastPtsWrite = Global.NO_PTS; 
    public static final long MICRO_SECONDS_BETWEEN_FRAMES = 
      (long) (Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES); 

    public static void main(String[] args) { 
     IMediaReader mediaReader = ToolFactory.makeReader(inputFilename); 
     // stipulate that we want BufferedImages created in BGR 24bit color space 
     mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); 
     mediaReader.addListener(new ImageSnapListener()); 
     // read out the contents of the media file and 
     // dispatch events to the attached listener 
     while (mediaReader.readPacket() == null); 
    } 

    private static class ImageSnapListener extends MediaListenerAdapter { 

     public void onVideoPicture(IVideoPictureEvent event) { 
      if (event.getStreamIndex() != mVideoStreamIndex) { 
       // if the selected video stream id is not yet set, go ahead an 
       // select this lucky video stream 
       if (mVideoStreamIndex == -1) { 
        mVideoStreamIndex = event.getStreamIndex(); 
       } // no need to show frames from this video stream 
       else { 
        return; 
       } 
      } 
      // if uninitialized, back date mLastPtsWrite to get the very first frame 
      if (mLastPtsWrite == Global.NO_PTS) { 
       mLastPtsWrite = event.getTimeStamp() - MICRO_SECONDS_BETWEEN_FRAMES; 
      } 
      // if it's time to write the next frame 
      if (event.getTimeStamp() - mLastPtsWrite 
        >= MICRO_SECONDS_BETWEEN_FRAMES) { 
       String outputFilename = dumpImageToFile(event.getImage()); 
       // indicate file written 
       double seconds = ((double) event.getTimeStamp()) 
         /Global.DEFAULT_PTS_PER_SECOND; 
       System.out.printf("at elapsed time of %6.3f seconds wrote: %s\n", 
         seconds, outputFilename); 
       // update last write time 
       mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES; 
      } 
     } 

     private String dumpImageToFile(BufferedImage image) { 
      try { 
       String outputFilename = outputFilePrefix 
         + System.currentTimeMillis() + ".png"; 
       ImageIO.write(image, "png", new File(outputFilename)); 
       return outputFilename; 
      } catch (IOException e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 
    } 
} 
+0

이 코드가 모두 귀하의 코드입니까? 어쩌면 메신저가 없어졌지만 가져 오기 문 목록처럼 보입니다. – Deepend

+0

그게 내가 가진 모든 코드입니다. –

답변

1

나는이 오래된 질문은 알고 있지만 오늘 Xuggler와 함께 재생하는 동안 내가 튜토리얼 동일한 코드 조각을 발견했다. 여러 축소판을 받고있는 이유는 다음 줄에 있습니다 :

public static final double SECONDS_BETWEEN_FRAMES = 10; 

이 변수는 dumpImageToFile 호출 사이의 시간 (초)을 지정합니다. 그래서 프레임 썸네일 등등 ​​20.00 초, 10.00 초, 0.00 초에 기록 될 것입니다 :

if (event.getTimeStamp() - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) 

는 사용하여 비디오의 지속 시간을 계산할 수 있습니다 비디오의 중간에서 프레임 축소판을 얻으려면 XugglerJavaCodeGeeks에서 자습서에서 찾은 기능. 그런 다음 ImageSnapListener에서 코드를 변경하여 IVideoPictureEvent 이벤트 시간 소인이 계산 된 중간 점을 초과하면 단일 프레임 만 작성하십시오.

나는이 질문에 비틀 거린 사람을 돕기를 바랍니다.

2

가능한 방법입니다.

 public class ThumbsGenerator { 

     private static void processFrame(IVideoPicture picture, BufferedImage image) { 
       try { 

        File file=new File("C:\\snapshot\thimbnailpic.png");//name of pic 
        ImageIO.write(image, "png", file); 


      } catch (Exception e) { 
        e.printStackTrace(); 
      } 
    } 


    @SuppressWarnings("deprecation") 
    public static void main(String[] args) throws NumberFormatException,IOException { 

      String filename = "your_video.mp4"; 

      if (!IVideoResampler.isSupported(IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION)) 
      throw new RuntimeException("you must install the GPL version of Xuggler (with IVideoResampler support) for this demo to work"); 


      IContainer container = IContainer.make(); 


      if (container.open(filename, IContainer.Type.READ, null) < 0) 
        throw new IllegalArgumentException("could not open file: " 
            + filename); 


      String seconds=container.getDuration()/(1000000*2)+""; // time of thumbnail 

      int numStreams = container.getNumStreams(); 

      // and iterate through the streams to find the first video stream 
      int videoStreamId = -1; 
      IStreamCoder videoCoder = null; 
      for (int i = 0; i < numStreams; i++) { 
        // find the stream object 
        IStream stream = container.getStream(i); 
        // get the pre-configured decoder that can decode this stream; 
        IStreamCoder coder = stream.getStreamCoder(); 

        if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { 
          videoStreamId = i; 
          videoCoder = coder; 
          break; 
        } 
      } 

      if (videoStreamId == -1) 
        throw new RuntimeException( 
            "could not find video stream in container: " + filename); 



      if (videoCoder.open() < 0) 
        throw new RuntimeException( 
            "could not open video decoder for container: " + filename); 

      IVideoResampler resampler = null; 
      if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) { 


        resampler = IVideoResampler.make(videoCoder.getWidth(), videoCoder 
            .getHeight(), IPixelFormat.Type.BGR24, videoCoder 
            .getWidth(), videoCoder.getHeight(), videoCoder 
            .getPixelType()); 
        if (resampler == null) 
          throw new RuntimeException( 
              "could not create color space resampler for: " 
              + filename); 
      } 


      IPacket packet = IPacket.make(); 


      IRational timeBase = container.getStream(videoStreamId).getTimeBase(); 


      System.out.println("Timebase " + timeBase.toString()); 


      long timeStampOffset = (timeBase.getDenominator()/timeBase.getNumerator()) 
            * Integer.parseInt(seconds); 
      System.out.println("TimeStampOffset " + timeStampOffset); 


      long target = container.getStartTime() + timeStampOffset; 


      container.seekKeyFrame(videoStreamId, target, 0); 

      boolean isFinished = false; 

      while(container.readNextPacket(packet) >= 0 && !isFinished) { 




        if (packet.getStreamIndex() == videoStreamId) { 


          IVideoPicture picture = IVideoPicture.make(videoCoder 
              .getPixelType(), videoCoder.getWidth(), videoCoder 
              .getHeight()); 

          int offset = 0; 
          while (offset < packet.getSize()) { 


            int bytesDecoded = videoCoder.decodeVideo(picture, packet, 
                offset); 
            if (bytesDecoded < 0) { 
              System.err.println("WARNING!!! got no data decoding " + 
                  "video in one packet"); 
            } 
            offset += bytesDecoded; 



            picture from 


            if (picture.isComplete()) { 

              IVideoPicture newPic = picture; 



              if (resampler != null) { 

                newPic = IVideoPicture.make(resampler 
                    .getOutputPixelFormat(), picture.getWidth(), 
                    picture.getHeight()); 
                if (resampler.resample(newPic, picture) < 0) 
                  throw new RuntimeException( 
                      "could not resample video from: " 
                      + filename); 
              } 

              if (newPic.getPixelType() != IPixelFormat.Type.BGR24) 
                throw new RuntimeException( 
                    "could not decode video as BGR 24 bit data in: " 
                    + filename); 


              BufferedImage javaImage = Utils.videoPictureToImage(newPic); 


              processFrame(newPic, javaImage); 
              isFinished = true; 
            } 
          } 
        } 
      } 


      if (videoCoder != null) { 
        videoCoder.close(); 
        videoCoder = null; 
      } 
      if (container != null) { 
        container.close(); 
        container = null; 
      } 
    } } 
+0

저에게 맞는 작품 ... –