{"id":367,"date":"2011-02-14T18:59:00","date_gmt":"2011-02-14T18:59:00","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/2012\/10\/xuggler-tutorial-transcoding-and-media-modification.html"},"modified":"2012-10-21T19:36:29","modified_gmt":"2012-10-21T19:36:29","slug":"xuggler-tutorial-transcoding-media","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html","title":{"rendered":"Xuggler Tutorial: Transcoding and Media Modification"},"content":{"rendered":"<div dir=\"ltr\" style=\"text-align: left\"><i><strong>Note:<\/strong> This is part of our \u201c<a href=\"http:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-development-tutorials.html\">Xuggler Development Tutorials<\/a>\u201d series.<\/i><\/p>\n<p>In my previous tutorial, I performed a short <a href=\"http:\/\/www.javacodegeeks.com\/2011\/02\/introduction-xuggler-video-manipulation.html\">Introduction to Xuggler for Video Manipulation<\/a>. In this part, we are going to see some more exciting capabilities provided by <a href=\"http:\/\/www.xuggle.com\/xuggler\/\">Xuggler<\/a> and <a href=\"http:\/\/ffmpeg.org\/\">FFmpeg<\/a>, like video transcoding and media modification. Don&#8217;t forget that <a href=\"http:\/\/www.xuggle.com\/xuggler\/\">Xuggler<\/a> is a Java library that can be used to uncompress, manipulate, and compress recorded or live video in real time. <\/p>\n<p>Xuggler offers two distinct programming APIs which can be used for the same purpose. First, we have the <a href=\"http:\/\/wiki.xuggle.com\/MediaTool_Introduction\">MediaTool API<\/a>:<\/p>\n<p><span style=\"font-style: italic\">MediaTool is a simple Application Programming Interface (API) for decoding, encoding and modifying video in Java. MediaTool hides many of the nitty-gritty details of containers, codecs, and others so you can focus on the media, and not the tools. That said, MediaTool still provides access to the underlying Xuggler objects, so you have fine grain control if you need it.<\/span><\/p>\n<p>And then there is the <a href=\"http:\/\/wiki.xuggle.com\/Tutorials#Writing_Your_First_Xuggler_Advanced_API_Program\">Xuggler Advanced API<\/a>, which allows you to delve into the details of video manipulation, but adds a layer of complexity.<\/p>\n<p>To begin, we will use the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/package-summary.html\">MediaTool API<\/a> and in subsequent tutorials we will also deal with the Advanced API too.<\/p>\n<p>Let&#8217;s start by <a href=\"http:\/\/wiki.xuggle.com\/MediaTool_Introduction#How_To_Transcode_Media_From_One_Format_To_Another\">transcoding media<\/a> from one format to another. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Transcode\">Transcoding<\/a> is the direct digital-to-digital conversion of one <a href=\"http:\/\/en.wikipedia.org\/wiki\/Encoder\">encoding<\/a> to another. This is usually done in cases where a target device does not support the format or has limited storage capacity that mandates a reduced file size, or to convert incompatible or obsolete data to a better-supported or modern format. Transcoding is commonly a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Lossy_compression\">lossy process<\/a>, where &#8220;lossy&#8221; compression is a data encoding method which discards (loses) some of the data, in order to achieve its goal, with the result that decompressing the data yields content that is different from the original, though similar enough to be useful in some way.<\/p>\n<p>Let&#8217;s see some high level code for transcoding and I will explain the details later.<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.xuggler;\r\n\r\nimport com.xuggle.mediatool.IMediaReader;\r\nimport com.xuggle.mediatool.IMediaViewer;\r\nimport com.xuggle.mediatool.IMediaWriter;\r\nimport com.xuggle.mediatool.ToolFactory;\r\n\r\npublic class TranscodingExample {\r\n\r\n    private static final String inputFilename = \"c:\/myvideo.mp4\";\r\n    private static final String outputFilename = \"c:\/myvideo.flv\";\r\n\r\n    public static void main(String[] args) {\r\n\r\n        \/\/ create a media reader\r\n        IMediaReader mediaReader = \r\n               ToolFactory.makeReader(inputFilename);\r\n        \r\n        \/\/ create a media writer\r\n        IMediaWriter mediaWriter = \r\n               ToolFactory.makeWriter(outputFilename, mediaReader);\r\n\r\n        \/\/ add a writer to the reader, to create the output file\r\n        mediaReader.addListener(mediaWriter);\r\n        \r\n        \/\/ create a media viewer with stats enabled\r\n        IMediaViewer mediaViewer = ToolFactory.makeViewer(true);\r\n        \r\n        \/\/ add a viewer to the reader, to see the decoded media\r\n        mediaReader.addListener(mediaViewer);\r\n\r\n        \/\/ read and decode packets from the source file and\r\n        \/\/ and dispatch decoded audio and video to the writer\r\n        while (mediaReader.readPacket() == null) ;\r\n\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>With a few lines of code, we are able to convert an <a href=\"http:\/\/en.wikipedia.org\/wiki\/MPEG-4\">MPEG-4<\/a> input file to a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Flash_Video\">FLV<\/a> one. We start by creating an <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaReader.html\">IMediaReader<\/a> which is used to read and decode media. It opens up a media container, reads packets from it, decodes the data, and then dispatches information about the data to any registered <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaListener.html\">IMediaListener<\/a> objects. This is where the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaWriter.html\">IMediaWriter<\/a> class comes into play. It encodes and decodes media, handling both audio and video streams. To make things more interesting, we also attach an <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaViewer.html\">IMediaViewer<\/a> to our reader. This is used as a debuging tool, allowing us to view the video while it is being decoded. Additionally, we are presented with various stats during the process. Note that this class is in experimental mode, meaning it has some bugs where it can hang, so handle with care.<\/p>\n<p>Essentially, with the above code, we attach our two listeners, the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaWriter.html\">IMediaWriter<\/a> and the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaViewer.html\">IMediaViewer<\/a>, to our <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaReader.html\">IMediaReader<\/a> object and we handle the callbacks while the reader reads and decodes packets from the source file. This is performed in the \u201cwhile\u201d loop. If we run the application with a sample input file, we will be presented with a screen similar to this:<\/p>\n<p><a href=\"http:\/\/3.bp.blogspot.com\/-FsEYcQqjPgg\/TVfgQlTnLuI\/AAAAAAAAAUg\/Sxys4rfTqoU\/s1600\/01-transcoding-input.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/3.bp.blogspot.com\/-FsEYcQqjPgg\/TVfgQlTnLuI\/AAAAAAAAAUg\/Sxys4rfTqoU\/s320\/01-transcoding-input.png\" style=\"cursor: pointer;height: 199px;margin: 0px auto 10px;text-align: center;width: 320px\" \/><\/a><div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p><a href=\"http:\/\/2.bp.blogspot.com\/-9Pemci3d1_c\/TVfgW8ORmDI\/AAAAAAAAAUo\/wdFQgFI8Hds\/s1600\/02-transcoding-stats.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/2.bp.blogspot.com\/-9Pemci3d1_c\/TVfgW8ORmDI\/AAAAAAAAAUo\/wdFQgFI8Hds\/s320\/02-transcoding-stats.png\" style=\"cursor: pointer;height: 216px;margin: 0px auto 10px;text-align: center;width: 320px\" \/><\/a><\/p>\n<p>After the process is completed (it will last as long as the source video file since we are simultaneously viewing it in real time), a new output file will have been created in FLV format.<\/p>\n<p>Let&#8217;s use Ffmpeg from command line in order to compare the input and output files:<\/p>\n<p><span style=\"font-style: italic\">ffmpeg.exe -i c:\/myvideo.mp4<br \/>\nSeems stream 1 codec frame rate differs from container frame rate: 59.92 (14981\/250) -&gt; 29.96 (14981\/500)<br \/>\nInput #0, mov,mp4,m4a,3gp,3g2,mj2, from &#8216;c:\/myvideo.mp4&#8217;:<br \/>\nMetadata:<br \/>\nmajor_brand     : mp42<br \/>\nminor_version   : 0<br \/>\ncompatible_brands: isomavc1mp42<br \/>\nDuration: 00:04:20.96, start: 0.000000, bitrate: 582 kb\/s<br \/>\nStream #0.0(und): Audio: aac, 44100 Hz, stereo, s16, 115 kb\/s<br \/>\nStream #0.1(und): Video: h264, yuv420p, 480&#215;270 [PAR 1:1 DAR 16:9], 464 kb\/s, 29.96 fps, 29.96 tbr, 29962 tbn, 59.92 tbc<\/span><\/p>\n<p>In the original video file, the container is <a href=\"http:\/\/en.wikipedia.org\/wiki\/MPEG-4\">MPEG-4<\/a> and there are two streams: an audio stream using <a href=\"http:\/\/en.wikipedia.org\/wiki\/Advanced_Audio_Coding\">AAC<\/a> at 44100Hz and a video stream using <a href=\"http:\/\/en.wikipedia.org\/wiki\/H.264\">H.264<\/a>.<\/p>\n<p><span style=\"font-style: italic\">ffmpeg.exe -i c:\/myvideo.flv<br \/>\nSeems stream 0 codec frame rate differs from container frame rate: 1000.00 (1000\/1) -&gt; 29.97 (30000\/1001)<br \/>\nInput #0, flv, from &#8216;c:\/myvideo.flv&#8217;:<br \/>\nMetadata:<br \/>\nduration        : 261<br \/>\nwidth           : 480<br \/>\nheight          : 270<br \/>\nvideodatarate   : 62<br \/>\nframerate       : 30<br \/>\nvideocodecid    : 2<br \/>\naudiodatarate   : 62<br \/>\naudiosamplerate : 44100<br \/>\naudiosamplesize : 16<br \/>\nstereo          : true<br \/>\naudiocodecid    : 2<br \/>\nfilesize        : 43117478<br \/>\nDuration: 00:04:20.98, start: 0.000000, bitrate: 128 kb\/s<br \/>\nStream #0.0: Video: flv, yuv420p, 480&#215;270, 64 kb\/s, 29.97 tbr, 1k tbn, 1k tbc<br \/>\nStream #0.1: Audio: mp3, 44100 Hz, 2 channels, s16, 64 kb\/s<\/span><\/p>\n<p>After the transcoding, the generated Flash video file uses an FLV video stream and an <a href=\"http:\/\/en.wikipedia.org\/wiki\/MP3\">MP3<\/a> audio stream.<\/p>\n<p>We are now ready to modify a media file using Xuggler. But before we write code, we need to understand <a href=\"http:\/\/wiki.xuggle.com\/MediaTool_Introduction#How_MediaTool_Works\">how MediaTool works<\/a>:<\/p>\n<p><span style=\"font-style: italic\">MediaTool uses an event listener paradigm. The writer is automatically added as a &#8220;listener&#8221; to the reader and receives all decoded media. The IMediaViewer and IMediaWriter interfaces (what the viewer and writer actually are) implement the IMediaListener interface, and may be added as listeners to an IMediaReader.<\/span><\/p>\n<p>We confirmed that with our previous example. The thing is that in order to perform various <a href=\"http:\/\/wiki.xuggle.com\/MediaTool_Introduction#How_To_Modify_Media_In_A_File\">modifications to an input file<\/a>, we have to set up a &#8220;media pipeline&#8221;. We create custom implementations of <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaTool.html\">IMediaTool<\/a> and then set up listeners on each tool in a chain way so they pass data from one to the other.<\/p>\n<p>Let&#8217;s suppose we wish to add a static image to our video and at the same time we wish to reduce the audio volume. In that case, we create two custom <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaTool.html\">IMediaTool<\/a> objects:<\/p>\n<ul style=\"text-align: left\">\n<li>StaticImageMediaTool: Takes a video picture and stamps a static image file on a specific location on the screen.<\/li>\n<li>VolumeAdjustMediaTool: Adjusts volume by a constant factor.<\/li>\n<\/ul>\n<p>Additionally, we create an <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaWriter.html\">IMediaWriter<\/a> object which will be used for the output file creation. With all those, we create a chain that goes as follows:<\/p>\n<p><span style=\"font-weight: bold\">reader -&gt; addStaticImage -&gt; reduceVolume -&gt; writer<span style=\"font-style: italic\"><\/span><\/span><\/p>\n<p>Let&#8217;s see the code that implements all the above:<\/p>\n<pre class=\"brush:java\">package com.javacodegeeks.xuggler;\r\n\r\nimport java.awt.Color;\r\nimport java.awt.Graphics2D;\r\nimport java.awt.geom.Rectangle2D;\r\nimport java.awt.image.BufferedImage;\r\nimport java.io.File;\r\nimport java.io.IOException;\r\nimport java.nio.ShortBuffer;\r\n\r\nimport javax.imageio.ImageIO;\r\n\r\nimport com.xuggle.mediatool.IMediaReader;\r\nimport com.xuggle.mediatool.IMediaTool;\r\nimport com.xuggle.mediatool.IMediaWriter;\r\nimport com.xuggle.mediatool.MediaToolAdapter;\r\nimport com.xuggle.mediatool.ToolFactory;\r\nimport com.xuggle.mediatool.event.IAudioSamplesEvent;\r\nimport com.xuggle.mediatool.event.IVideoPictureEvent;\r\n\r\npublic class ModifyMediaExample {\r\n\r\n    private static final String inputFilename = \"c:\/myvideo.mp4\";\r\n    private static final String outputFilename = \"c:\/myvideo.flv\";\r\n    private static final String imageFilename = \"c:\/jcg_logo_small.png\";\r\n\r\n    public static void main(String[] args) {\r\n\r\n        \/\/ create a media reader\r\n        IMediaReader mediaReader = ToolFactory.makeReader(inputFilename);\r\n        \r\n        \/\/ configure it to generate BufferImages\r\n        mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);\r\n\r\n        IMediaWriter mediaWriter = \r\n               ToolFactory.makeWriter(outputFilename, mediaReader);\r\n        \r\n        IMediaTool imageMediaTool = new StaticImageMediaTool(imageFilename);\r\n        IMediaTool audioVolumeMediaTool = new VolumeAdjustMediaTool(0.1);\r\n        \r\n        \/\/ create a tool chain:\r\n        \/\/ reader -&gt; addStaticImage -&gt; reduceVolume -&gt; writer\r\n        mediaReader.addListener(imageMediaTool);\r\n        imageMediaTool.addListener(audioVolumeMediaTool);\r\n        audioVolumeMediaTool.addListener(mediaWriter);\r\n        \r\n        while (mediaReader.readPacket() == null) ;\r\n\r\n    }\r\n    \r\n    private static class StaticImageMediaTool extends MediaToolAdapter {\r\n        \r\n        private BufferedImage logoImage;\r\n        \r\n        public StaticImageMediaTool(String imageFile) {\r\n            \r\n            try {\r\n                logoImage = ImageIO.read(new File(imageFile));\r\n            } \r\n            catch (IOException e) {\r\n                e.printStackTrace();\r\n                throw new RuntimeException(\"Could not open file\");\r\n            }\r\n            \r\n        }\r\n\r\n        @Override\r\n        public void onVideoPicture(IVideoPictureEvent event) {\r\n            \r\n            BufferedImage image = event.getImage();\r\n            \r\n            \/\/ get the graphics for the image\r\n            Graphics2D g = image.createGraphics();\r\n            \r\n            Rectangle2D bounds = new \r\n              Rectangle2D.Float(0, 0, logoImage.getWidth(), logoImage.getHeight());\r\n\r\n            \/\/ compute the amount to inset the time stamp and \r\n            \/\/ translate the image to that position\r\n            double inset = bounds.getHeight();\r\n            g.translate(inset, event.getImage().getHeight() - inset);\r\n\r\n            g.setColor(Color.WHITE);\r\n            g.fill(bounds);\r\n            g.setColor(Color.BLACK);\r\n            g.drawImage(logoImage, 0, 0, null);\r\n            \r\n            \/\/ call parent which will pass the video onto next tool in chain\r\n            super.onVideoPicture(event);\r\n            \r\n        }\r\n        \r\n    }\r\n\r\n    private static class VolumeAdjustMediaTool extends MediaToolAdapter {\r\n        \r\n        \/\/ the amount to adjust the volume by\r\n        private double mVolume;\r\n        \r\n        public VolumeAdjustMediaTool(double volume) {\r\n            mVolume = volume;\r\n        }\r\n\r\n        @Override\r\n        public void onAudioSamples(IAudioSamplesEvent event) {\r\n            \r\n            \/\/ get the raw audio bytes and adjust it's value\r\n            ShortBuffer buffer = \r\n               event.getAudioSamples().getByteBuffer().asShortBuffer();\r\n            \r\n            for (int i = 0; i &lt; buffer.limit(); ++i) {\r\n                buffer.put(i, (short) (buffer.get(i) * mVolume));\r\n            }\r\n\r\n            \/\/ call parent which will pass the audio onto next tool in chain\r\n            super.onAudioSamples(event);\r\n            \r\n        }\r\n        \r\n    }\r\n\r\n}\r\n<\/pre>\n<p>As always, we first create an <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaReader.html\">IMediaReader<\/a> and use the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaReader.html#setBufferedImageTypeToGenerate%28int%29\">setBufferedImageTypeToGenerate<\/a> method to to generate <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/awt\/image\/BufferedImage.html\">BufferedImage<\/a> images when calling <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaListener.html#onVideoPicture%28com.xuggle.mediatool.event.IVideoPictureEvent%29\">IMediaListener.onVideoPicture<\/a>. This is necessary in order to overlay our custom image on top of the actual video pictures. We then create the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/IMediaWriter.html\">IMediaWriter<\/a> and the media tool objects and configure the tool chain as described above. Let&#8217;s take a closer look to the custom media tools.<\/p>\n<p>First, we have the StaticImageMediaTool class. It extends the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html\">MediaToolAdapter<\/a> and overrides the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html#onVideoPicture%28com.xuggle.mediatool.event.IVideoPictureEvent%29\">onVideoPicture<\/a> method since we wish to manipulate the video stream with this one. In the constructor, we have loaded an image file using the <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/javax\/imageio\/ImageIO.html#read%28java.io.File%29\">ImageIO.read<\/a> method. The <a href=\"http:\/\/4.bp.blogspot.com\/_tWwHCKnIbjs\/TErjgOFnKnI\/AAAAAAAAAAo\/Y9tAOEYds8I\/S1600-R\/logo.png\">JavaCodeGeeks logo<\/a> is used for that purpose (actually, a scaled down version of it). Then, in the implemented <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html#onVideoPicture%28com.xuggle.mediatool.event.IVideoPictureEvent%29\">onVideoPicture<\/a> method, we get the underlying <a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/awt\/image\/BufferedImage.html\">BufferedImage<\/a> by calling <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/event\/IVideoPictureEvent.html#getImage%28%29\">IVideoPictureEvent.getImage<\/a> and create a <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/awt\/Graphics2D.html\">Graphics2D<\/a> object. We then use the <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/awt\/Graphics.html#drawImage%28java.awt.Image,%20int,%20int,%20java.awt.image.ImageObserver%29\">Graphics.drawImage<\/a> method to overlay the static image. Finally, we call the parent <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html#onVideoPicture%28com.xuggle.mediatool.event.IVideoPictureEvent%29\">onVideoPicture<\/a> method which will pass the video onto next tool in chain.<\/p>\n<p>Then, we have the VolumeAdjustMediaTool. It also extends the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html\">MediaToolAdapter<\/a>, but overrides the <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html#onAudioSamples%28com.xuggle.mediatool.event.IAudioSamplesEvent%29\">onAudioSamples<\/a> method, which is called after audio samples have been decoded or encoded. There, we get the raw audio bytes by calling <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/event\/IAudioSamplesEvent.html#getAudioSamples%28%29\">IAudioSamplesEvent.getAudioSamples<\/a> and adjust it&#8217;s value by using the corresponding <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/nio\/ShortBuffer.html\">ShortBuffer<\/a> class. Again, after our custom processing, we call the parent <a href=\"http:\/\/build.xuggle.com\/view\/Stable\/job\/xuggler_jdk5_stable\/javadoc\/java\/api\/com\/xuggle\/mediatool\/MediaToolAdapter.html#onAudioSamples%28com.xuggle.mediatool.event.IAudioSamplesEvent%29\">onAudioSamples<\/a> method which will pass the audio onto next tool in chain.  If we now run this application, we will see the added image on top of the original video and the audio volume will have been considerably reduced.<br \/>\n<a href=\"http:\/\/3.bp.blogspot.com\/-D5X9Hr9mUmI\/TVfiK5_Gr2I\/AAAAAAAAAUw\/QajRg7DjCyw\/s1600\/03-media-modification.png\"><img decoding=\"async\" alt=\"\" border=\"0\" src=\"http:\/\/3.bp.blogspot.com\/-D5X9Hr9mUmI\/TVfiK5_Gr2I\/AAAAAAAAAUw\/QajRg7DjCyw\/s320\/03-media-modification.png\" style=\"cursor: pointer;height: 179px;margin: 0px auto 10px;text-align: center;width: 320px\" \/><\/a>  That&#8217;s it. Transcoding and media manipulation powered by <a href=\"http:\/\/www.xuggle.com\/xuggler\/\">Xuggler<\/a>. As always, you can <a href=\"http:\/\/dl.dropbox.com\/u\/7215751\/JavaCodeGeeks\/XugglerTranscodingMediaModificationTutorial\/XugglerTutorialProject_Part02.zip\">download the Eclipse project<\/a> created for this tutorial.  Stay tuned for more <a href=\"http:\/\/www.xuggle.com\/xuggler\/\">Xuggler<\/a> tutorials here at <a href=\"http:\/\/www.javacodegeeks.com\/\">JavaCodeGeeks<\/a>! And don&#8217;t forget to share!<\/p>\n<p><strong>Related Articles:<\/strong><\/p>\n<ul style=\"text-align: left\">\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/02\/introduction-xuggler-video-manipulation.html\">Introduction to Xuggler for Video Manipulation<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-frames-capture-video.html\">Xuggler Tutorial: Frames Capture and Video Creation<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/05\/rtmp-to-rtsp-re-stream-using-wowza-and.html\">RTMP To RTSP re-stream using wowza and xuggler<\/a><\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video Manipulation. In this part, we are going to see some more exciting capabilities provided by Xuggler and FFmpeg, like video transcoding and media modification. Don&#8217;t forget that Xuggler is a Java library &hellip;<\/p>\n","protected":false},"author":3,"featured_media":255,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[149,40],"class_list":["post-367","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-desktop-java","tag-ffmpeg","tag-xuggler"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2011-02-14T18:59:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-10-21T19:36:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ilias Tsagklis\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ilias Tsagklis\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html\"},\"author\":{\"name\":\"Ilias Tsagklis\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/9a83496b285d30c61e8a674625c1350e\"},\"headline\":\"Xuggler Tutorial: Transcoding and Media Modification\",\"datePublished\":\"2011-02-14T18:59:00+00:00\",\"dateModified\":\"2012-10-21T19:36:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html\"},\"wordCount\":1322,\"commentCount\":9,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/xuggler-logo.jpg\",\"keywords\":[\"FFmpeg\",\"Xuggler\"],\"articleSection\":[\"Desktop Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html\",\"name\":\"Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/xuggler-logo.jpg\",\"datePublished\":\"2011-02-14T18:59:00+00:00\",\"dateModified\":\"2012-10-21T19:36:29+00:00\",\"description\":\"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/xuggler-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/xuggler-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2011\\\/02\\\/xuggler-tutorial-transcoding-media.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Desktop Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/desktop-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Xuggler Tutorial: Transcoding and Media Modification\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/9a83496b285d30c61e8a674625c1350e\",\"name\":\"Ilias Tsagklis\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g\",\"caption\":\"Ilias Tsagklis\"},\"description\":\"Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.\",\"sameAs\":[\"http:\\\/\\\/www.iliastsagklis.com\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/iliastsagklis\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/ilias-tsagklis\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks","description":"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html","og_locale":"en_US","og_type":"article","og_title":"Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks","og_description":"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video","og_url":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2011-02-14T18:59:00+00:00","article_modified_time":"2012-10-21T19:36:29+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg","type":"image\/jpeg"}],"author":"Ilias Tsagklis","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Ilias Tsagklis","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html"},"author":{"name":"Ilias Tsagklis","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/9a83496b285d30c61e8a674625c1350e"},"headline":"Xuggler Tutorial: Transcoding and Media Modification","datePublished":"2011-02-14T18:59:00+00:00","dateModified":"2012-10-21T19:36:29+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html"},"wordCount":1322,"commentCount":9,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg","keywords":["FFmpeg","Xuggler"],"articleSection":["Desktop Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html","url":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html","name":"Xuggler Tutorial: Transcoding and Media Modification - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg","datePublished":"2011-02-14T18:59:00+00:00","dateModified":"2012-10-21T19:36:29+00:00","description":"Note: This is part of our \u201cXuggler Development Tutorials\u201d series. In my previous tutorial, I performed a short Introduction to Xuggler for Video","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/xuggler-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2011\/02\/xuggler-tutorial-transcoding-media.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Desktop Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/desktop-java"},{"@type":"ListItem","position":4,"name":"Xuggler Tutorial: Transcoding and Media Modification"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/9a83496b285d30c61e8a674625c1350e","name":"Ilias Tsagklis","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/43505f28bb49f6e290c24be0b209ccc1af350f0f6587025ffd4847ef44bf6b78?s=96&d=mm&r=g","caption":"Ilias Tsagklis"},"description":"Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.","sameAs":["http:\/\/www.iliastsagklis.com\/","https:\/\/www.linkedin.com\/in\/iliastsagklis"],"url":"https:\/\/www.javacodegeeks.com\/author\/ilias-tsagklis"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=367"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/367\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/255"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}