微信网站开发 新闻,网站浏览量怎么查看,手机网站怎么推广,手机如何编辑网页内容注意#xff1a;这是我们的“ Xuggler开发教程 ”系列的一部分。 在之前的教程中#xff0c;我对视频处理Xuggler进行了简短介绍 。 在这一部分中#xff0c;我们将看到Xuggler和FFmpeg提供的一些更令人兴奋的功能#xff0c;例如视频转码和媒体修改。 不要忘记Xuggler是一… 注意这是我们的“ Xuggler开发教程 ”系列的一部分。 在之前的教程中我对视频处理Xuggler进行了简短介绍 。 在这一部分中我们将看到Xuggler和FFmpeg提供的一些更令人兴奋的功能例如视频转码和媒体修改。 不要忘记Xuggler是一个Java库可用于实时解压缩处理和压缩录制的视频或实时视频。 Xuggler提供了两种不同的编程API可用于同一目的。 首先我们有MediaTool API MediaTool是一个简单的应用程序编程接口API用于对Java中的视频进行解码编码和修改。 MediaTool隐藏了许多容器编解码器和其他内容的细节因此您可以专注于媒体而不是工具。 就是说MediaTool仍然提供对基础Xuggler对象的访问因此如果需要您可以进行精细的控制。 还有Xuggler Advanced API 它使您可以深入研究视频操作的细节但又增加了一层复杂性。 首先我们将使用MediaTool API 在随后的教程中我们还将处理Advanced API。 让我们开始将媒体从一种格式转码为另一种格式。 代码转换是一种编码到另一种编码的直接数模转换。 通常在目标设备不支持格式或存储容量有限要求减小文件大小或将不兼容或过时的数据转换为更好支持的格式或现代格式的情况下执行此操作。 转码通常是一个有损过程 其中“有损”压缩是一种数据编码方法为了达到其目标它会丢弃丢失某些数据结果是对数据进行解压缩会产生与原始数据不同的内容尽管足够相似以某种方式有用。 让我们看一些用于转码的高级代码稍后我将详细解释。 package com.javacodegeeks.xuggler;import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.IMediaViewer;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;public class TranscodingExample {private static final String inputFilename c:/myvideo.mp4;private static final String outputFilename c:/myvideo.flv;public static void main(String[] args) {// create a media readerIMediaReader mediaReader ToolFactory.makeReader(inputFilename);// create a media writerIMediaWriter mediaWriter ToolFactory.makeWriter(outputFilename, mediaReader);// add a writer to the reader, to create the output filemediaReader.addListener(mediaWriter);// create a media viewer with stats enabledIMediaViewer mediaViewer ToolFactory.makeViewer(true);// add a viewer to the reader, to see the decoded mediamediaReader.addListener(mediaViewer);// read and decode packets from the source file and// and dispatch decoded audio and video to the writerwhile (mediaReader.readPacket() null) ;}} 只需几行代码我们就可以将MPEG-4输入文件转换为FLV文件。 我们首先创建一个IMediaReader 用于读取和解码媒体。 它打开一个媒体容器从中读取数据包解码数据然后将有关数据的信息分发到任何已注册的IMediaListener对象。 这是IMediaWriter类起作用的地方。 它对媒体进行编码和解码同时处理音频和视频流。 为了使事情变得更有趣我们还将IMediaViewer附加到我们的阅读器上。 它用作调试工具使我们可以在解码视频时观看视频。 此外在此过程中我们还会看到各种统计信息。 请注意该类处于实验模式这意味着它有一些可能会挂起的错误因此请谨慎处理。 本质上使用上面的代码我们将两个侦听器IMediaWriter和IMediaViewer附加到IMediaReader对象并在读取器读取和解码源文件中的数据包的同时处理回调。 这是在“ while”循环中执行的。 如果我们使用示例输入文件运行该应用程序将显示类似于以下的屏幕 该过程完成后由于我们正在同时实时查看因此该过程将与源视频文件一样长将以FLV格式创建一个新的输出文件。 让我们从命令行使用Ffmpeg来比较输入和输出文件 ffmpeg.exe -ic/myvideo.mp4 似乎流1编解码器的帧速率与容器的帧速率不同59.9214981/250- 29.9614981/500 从c/myvideo.mp4输入0movmp4m4a3gp3g2mj2 元数据 major_brandmp42 minor_version0 兼容品牌isomavc1mp42 持续时间000420.96开始0.000000比特率582 kb / s 流0.0und音频aac44100 Hz立体声s16、115 kb / s 流0.1und视频h264yuv420p480×270 [PAR 11 DAR 169]464 kb / s29.96 fps29.96 tbr29962 tbn59.92 tbc 在原始视频文件中容器为MPEG-4 有两个流使用44100Hz的AAC的音频流和使用H.264的视频流。 ffmpeg.exe -ic/myvideo.flv 似乎流0编解码器的帧速率与容器的帧速率不同1000.001000/1- 29.9730000/1001 从c/myvideo.flv输入0 flv 元数据 持续时间261 宽度480 高度270 videodatarate62 帧率30 videocodecid2 音频数据率62 音频采样率44100 音频样本大小16 立体声真 音频编解码器2 文件大小43117478 持续时间000420.98开始0.000000比特率128 kb / s 流0.0视频flvyuv420p480×270、64 kb / s29.97 tbr1k tbn1k tbc 流0.1音频mp344100 Hz2声道s1664 kb / s 转码后生成的Flash视频文件使用FLV视频流和MP3音频流。 现在我们准备使用Xuggler修改媒体文件。 但是在编写代码之前我们需要了解MediaTool的工作原理 MediaTool使用事件侦听器范例。 写入器会自动作为“侦听器”添加到读取器并接收所有解码的媒体。 IMediaViewer和IMediaWriter接口查看器和编写器实际上是什么实现IMediaListener接口并且可以作为侦听器添加到IMediaReader。 我们通过前面的示例确认了这一点。 问题是为了对输入文件进行各种修改 我们必须建立一个“媒体管道”。 我们创建IMediaTool的自定义实现然后以链式方式在每个工具上设置侦听器以便它们将数据从一个传递到另一个。 假设我们希望在视频中添加静态图像同时希望减少音频量。 在这种情况下我们将创建两个自定义IMediaTool对象 StaticImageMediaTool拍摄视频图片并在屏幕上的特定位置标记静态图像文件。 VolumeAdjustMediaTool按恒定因子调整音量。 另外我们创建一个IMediaWriter对象该对象将用于创建输出文件。 通过所有这些我们创建了一条链如下所示 读取器- addStaticImage- reduceVolume-写入器 让我们看看实现以上所有功能的代码 package com.javacodegeeks.xuggler;import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ShortBuffer;import javax.imageio.ImageIO;import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.IMediaTool;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.MediaToolAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IAudioSamplesEvent;
import com.xuggle.mediatool.event.IVideoPictureEvent;public class ModifyMediaExample {private static final String inputFilename c:/myvideo.mp4;private static final String outputFilename c:/myvideo.flv;private static final String imageFilename c:/jcg_logo_small.png;public static void main(String[] args) {// create a media readerIMediaReader mediaReader ToolFactory.makeReader(inputFilename);// configure it to generate BufferImagesmediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);IMediaWriter mediaWriter ToolFactory.makeWriter(outputFilename, mediaReader);IMediaTool imageMediaTool new StaticImageMediaTool(imageFilename);IMediaTool audioVolumeMediaTool new VolumeAdjustMediaTool(0.1);// create a tool chain:// reader - addStaticImage - reduceVolume - writermediaReader.addListener(imageMediaTool);imageMediaTool.addListener(audioVolumeMediaTool);audioVolumeMediaTool.addListener(mediaWriter);while (mediaReader.readPacket() null) ;}private static class StaticImageMediaTool extends MediaToolAdapter {private BufferedImage logoImage;public StaticImageMediaTool(String imageFile) {try {logoImage ImageIO.read(new File(imageFile));} catch (IOException e) {e.printStackTrace();throw new RuntimeException(Could not open file);}}Overridepublic void onVideoPicture(IVideoPictureEvent event) {BufferedImage image event.getImage();// get the graphics for the imageGraphics2D g image.createGraphics();Rectangle2D bounds new Rectangle2D.Float(0, 0, logoImage.getWidth(), logoImage.getHeight());// compute the amount to inset the time stamp and // translate the image to that positiondouble inset bounds.getHeight();g.translate(inset, event.getImage().getHeight() - inset);g.setColor(Color.WHITE);g.fill(bounds);g.setColor(Color.BLACK);g.drawImage(logoImage, 0, 0, null);// call parent which will pass the video onto next tool in chainsuper.onVideoPicture(event);}}private static class VolumeAdjustMediaTool extends MediaToolAdapter {// the amount to adjust the volume byprivate double mVolume;public VolumeAdjustMediaTool(double volume) {mVolume volume;}Overridepublic void onAudioSamples(IAudioSamplesEvent event) {// get the raw audio bytes and adjust its valueShortBuffer buffer event.getAudioSamples().getByteBuffer().asShortBuffer();for (int i 0; i buffer.limit(); i) {buffer.put(i, (short) (buffer.get(i) * mVolume));}// call parent which will pass the audio onto next tool in chainsuper.onAudioSamples(event);}}} 与往常一样我们首先创建一个IMediaReader并在调用IMediaListener.onVideoPicture时使用setBufferedImageTypeToGenerate方法生成BufferedImage图像。 为了将我们的自定义图像覆盖在实际的视频图片上这是必要的。 然后我们创建IMediaWriter和媒体工具对象并如上所述配置工具链。 让我们仔细看看自定义媒体工具。 首先我们有StaticImageMediaTool类。 它扩展了MediaToolAdapter并覆盖了onVideoPicture方法因为我们希望使用这一方法来处理视频流。 在构造函数中我们已经使用ImageIO.read方法加载了一个图像文件。 JavaCodeGeeks徽标用于此目的实际上是其缩小版本。 然后在已实现的onVideoPicture方法中我们通过调用IVideoPictureEvent.getImage获得基础的BufferedImage并创建一个Graphics2D对象。 然后我们使用Graphics.drawImage方法覆盖静态图像。 最后我们调用父级onVideoPicture方法该方法会将视频传递到链中的下一个工具。 然后我们有了VolumeAdjustMediaTool。 它还扩展了MediaToolAdapter 但覆盖了onAudioSamples方法该方法在对音频样本进行解码或编码后调用。 在那里我们通过调用IAudioSamplesEvent.getAudioSamples来获取原始音频字节并使用相应的ShortBuffer类调整其值。 再次在自定义处理之后我们调用父onAudioSamples方法该方法会将音频传递到链中的下一个工具。 如果现在运行此应用程序我们将在原始视频的顶部看到添加的图像并且音频音量将大大降低。 而已。 Xuggler支持的转码和媒体处理。 与往常一样您可以下载为本教程创建的Eclipse项目 。 请继续关注JavaCodeGeeks上的更多Xuggler教程 别忘了分享 相关文章 Xuggler视频处理简介 Xuggler教程帧捕获和视频创建 使用wowza和xuggler将RTMP转换为RTSP 翻译自: https://www.javacodegeeks.com/2011/02/xuggler-tutorial-transcoding-media.html