2010-07-09 3 views
13

Java 응용 프로그램에서 생성 된 라이브 비디오를 스트리밍하는 방법을 찾으려고합니다. 응용 프로그램은 자체 스크린 샷을 찍어 비디오 스트림으로 인코딩하고 스트림을 게시해야합니다.Java 응용 프로그램 내에서 라이브 비디오를 전송하는 방법은 무엇입니까?

지금까지 Xuggler (FFMPEG의 맨 위에있는 Java 라이브러리)을 사용하여 스크린 샷을 비디오 파일로 인코딩했습니다. 이것은 잘 작동합니다. Xuggler는 RTMP를 통해 실시간 비디오를 전송할 수 있다고 주장하지만 프로그래밍 방식으로이 작업을 수행하는 방법에 대한 문서는 찾지 못했습니다.

  1. Xuggler에서 프로그래밍 방식으로 RTMP 비디오를 스트리밍하는 방법을 아는 사람이 있습니까?
  2. 누구나 동일한 결과를 얻기 위해 사용할 수있는 다른 라이브러리에 대한 제안 사항이 있습니까? RTP를 통해 MPEG2로 비디오를 스트리밍하는 것을 선호합니다.

나는 Xuggler 공개 토론 here에 아주 유사한 질문을하는 누군가를 찾아 냈습니다.

나는 JMF를 들여다 보았고 다른 이유로는 옵션이 아닙니다.

답변

20

솔직히 JMF로 시간을 낭비하지 마십시오. 다음은 h.264를 사용하여 rtmp 스트림으로 스크린 샷을 찍는 방법입니다 (이 예는 [email protected] 덕분입니다). 코드가 여기에 표시되지 않는 경우 : http://pastebin.com/sJHwj0nW

import com.xuggle.xuggler.Configuration; 
import com.xuggle.xuggler.ICodec; 
import com.xuggle.xuggler.IContainer; 
import com.xuggle.xuggler.IContainerFormat; 
import com.xuggle.xuggler.IPacket; 
import com.xuggle.xuggler.IPixelFormat; 
import com.xuggle.xuggler.IRational; 
import com.xuggle.xuggler.IStream; 
import com.xuggle.xuggler.IStreamCoder; 
import com.xuggle.xuggler.IVideoPicture; 
import com.xuggle.xuggler.video.ConverterFactory; 
import com.xuggle.xuggler.video.IConverter; 
import java.awt.AWTException; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 

public class XugglerRtmpReferenceImpl { 

    private static String url = "rtmp://your.test.server/screen/"; 
    private static String fileName = "test/teststream"; 
    private static int framesToEncode = 60; 
    private static int x = 0; 
    private static int y = 0; 
    private static int height = 480; 
    private static int width = 640; 

    public static void main(String[] args) { 
     IContainer container = IContainer.make(); 
     IContainerFormat containerFormat_live = IContainerFormat.make(); 
     containerFormat_live.setOutputFormat("flv", url + fileName, null); 
     container.setInputBufferLength(0); 
     int retVal = container.open(url + fileName, IContainer.Type.WRITE, containerFormat_live); 
     if (retVal < 0) { 
      System.err.println("Could not open output container for live stream"); 
      System.exit(1); 
     } 
     IStream stream = container.addNewStream(0); 
     IStreamCoder coder = stream.getStreamCoder(); 
     ICodec codec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264); 
     coder.setNumPicturesInGroupOfPictures(5); 
     coder.setCodec(codec); 
     coder.setBitRate(200000); 
     coder.setPixelType(IPixelFormat.Type.YUV420P); 
     coder.setHeight(height); 
     coder.setWidth(width); 
     System.out.println("[ENCODER] video size is " + width + "x" + height); 
     coder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, true); 
     coder.setGlobalQuality(0); 
     IRational frameRate = IRational.make(5, 1); 
     coder.setFrameRate(frameRate); 
     coder.setTimeBase(IRational.make(frameRate.getDenominator(), frameRate.getNumerator())); 
     Properties props = new Properties(); 
     InputStream is = XugglerRtmpReferenceImpl.class.getResourceAsStream("/libx264-normal.ffpreset"); 
     try { 
      props.load(is); 
     } catch (IOException e) { 
      System.err.println("You need the libx264-normal.ffpreset file from the Xuggle distribution in your classpath."); 
      System.exit(1); 
     } 
     Configuration.configure(props, coder); 
     coder.open(); 
     container.writeHeader(); 
     long firstTimeStamp = System.currentTimeMillis(); 
     long lastTimeStamp = -1; 
     int i = 0; 
     try { 
      Robot robot = new Robot(); 
      while (i < framesToEncode) { 
       //long iterationStartTime = System.currentTimeMillis(); 
       long now = System.currentTimeMillis(); 
       //grab the screenshot 
       BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height)); 
       //convert it for Xuggler 
       BufferedImage currentScreenshot = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 
       currentScreenshot.getGraphics().drawImage(image, 0, 0, null); 
       //start the encoding process 
       IPacket packet = IPacket.make(); 
       IConverter converter = ConverterFactory.createConverter(currentScreenshot, IPixelFormat.Type.YUV420P); 
       long timeStamp = (now - firstTimeStamp) * 1000; 
       IVideoPicture outFrame = converter.toPicture(currentScreenshot, timeStamp); 
       if (i == 0) { 
        //make first frame keyframe 
        outFrame.setKeyFrame(true); 
       } 
       outFrame.setQuality(0); 
       coder.encodeVideo(packet, outFrame, 0); 
       outFrame.delete(); 
       if (packet.isComplete()) { 
        container.writePacket(packet); 
        System.out.println("[ENCODER] writing packet of size " + packet.getSize() + " for elapsed time " + ((timeStamp - lastTimeStamp)/1000)); 
        lastTimeStamp = timeStamp; 
       } 
       System.out.println("[ENCODER] encoded image " + i + " in " + (System.currentTimeMillis() - now)); 
       i++; 
       try { 
        Thread.sleep(Math.max((long) (1000/frameRate.getDouble()) - (System.currentTimeMillis() - now), 0)); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } catch (AWTException e) { 
      e.printStackTrace(); 
     } 
     container.writeTrailer(); 
    } 
} 
+0

시도해보십시오. 코드 블록이 너무 길어 보입니다. –

+2

감사합니다. 이것은 올바른 방향으로 나를 가리키는 데 도움이되었습니다. – Tansir1

+0

xuggler는 카메라 및 마이크에서 스트리밍 비디오를 라이브로 수신합니다 –

관련 문제