Java 简陋的视频拍摄给定时间的快照
您好,我正在使用一个视频缩略图。 到目前为止,我已经成功地通过以下方法从一个视频开始拍摄快照Java 简陋的视频拍摄给定时间的快照,java,video,ffmpeg,Java,Video,Ffmpeg,您好,我正在使用一个视频缩略图。 到目前为止,我已经成功地通过以下方法从一个视频开始拍摄快照 private static Path generateThumbnail(final Path videoFile) throws InterruptedException, IOException { final Demuxer demuxer = Demuxer.make(); demuxer.open(videoFile.toString(), null, false, true
private static Path generateThumbnail(final Path videoFile)
throws InterruptedException, IOException {
final Demuxer demuxer = Demuxer.make();
demuxer.open(videoFile.toString(), null, false, true, null, null);
int streamIndex = -1;
Decoder videoDecoder = null;
String rotate = null;
final int numStreams = demuxer.getNumStreams();
for (int i = 0; i < numStreams; ++i) {
final DemuxerStream stream = demuxer.getStream(i);
final KeyValueBag metaData = stream.getMetaData();
final Decoder decoder = stream.getDecoder();
if (decoder != null
&& decoder.getCodecType() == MediaDescriptor.Type.MEDIA_VIDEO) {
videoDecoder = decoder;
streamIndex = i;
rotate = metaData.getValue("rotate", KeyValueBag.Flags.KVB_NONE);
break;
}
}
if (videoDecoder == null) {
throw new IOException("Not a valid video file");
}
videoDecoder.open(null, null);
final MediaPicture picture = MediaPicture.make(videoDecoder.getWidth(),
videoDecoder.getHeight(), videoDecoder.getPixelFormat());
final MediaPictureConverter converter = MediaPictureConverterFactory
.createConverter(MediaPictureConverterFactory.HUMBLE_BGR_24, picture);
final MediaPacket packet = MediaPacket.make();
BufferedImage image = null;
MUX : while (demuxer.read(packet) >= 0) {
if (packet.getStreamIndex() != streamIndex) {
continue;
}
int offset = 0;
int bytesRead = 0;
videoDecoder.decodeVideo(picture, packet, offset);
do {
bytesRead += videoDecoder.decode(picture, packet, offset);
if (picture.isComplete()) {
image = converter.toImage(null, picture);
break MUX;
}
offset += bytesRead;
} while (offset < packet.getSize());
}
if (image == null) {
throw new IOException("Unable to find a complete video frame");
}
if (rotate != null) {
final AffineTransform transform = new AffineTransform();
transform.translate(0.5 * image.getHeight(), 0.5 * image.getWidth());
transform.rotate(Math.toRadians(Double.parseDouble(rotate)));
transform.translate(-0.5 * image.getWidth(), -0.5 * image.getHeight());
final AffineTransformOp op = new AffineTransformOp(transform,
AffineTransformOp.TYPE_BILINEAR);
image = op.filter(image, null);
}
final Path target = videoFile.getParent()
.resolve(videoFile.getFileName() + ".thumb.jpg");
final double mul;
if (image.getWidth() > image.getHeight()) {
mul = 216 / (double) image.getWidth();
} else {
mul = 216 / (double) image.getHeight();
}
final int newW = (int) (image.getWidth() * mul);
final int newH = (int) (image.getHeight() * mul);
final Image thumbnailImage = image.getScaledInstance(newW, newH,
Image.SCALE_SMOOTH);
image = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_BGR);
final Graphics2D g2d = image.createGraphics();
g2d.drawImage(thumbnailImage, 0, 0, null);
g2d.dispose();
ImageIO.write(image, "jpeg", target.toFile());
return target.toAbsolutePath(); }
专用静态路径生成缩略图(最终路径视频文件)
抛出InterruptedException,IOException{
final Demuxer Demuxer=Demuxer.make();
open(videoFile.toString(),null,false,true,null,null);
int streamIndex=-1;
解码器videoDecoder=null;
字符串旋转=空;
final int numStreams=demuxer.getNumStreams();
对于(int i=0;i=0){
if(packet.getStreamIndex()!=streamIndex){
继续;
}
整数偏移=0;
int字节读取=0;
视频解码器。解码视频(图片、数据包、偏移量);
做{
字节读取+=视频解码器。解码(图片、数据包、偏移量);
if(picture.isComplete()){
image=converter.toImage(空,图片);
中断多路复用器;
}
偏移量+=字节读取;
}while(offsetimage.getHeight()){
mul=216/(双精度)image.getWidth();
}否则{
mul=216/(双精度)image.getHeight();
}
final int newW=(int)(image.getWidth()*mul);
final int newH=(int)(image.getHeight()*mul);
最终图像thumbnailImage=Image.getScaledInstance(newW,newH,
图像。缩放(平滑);
image=newbufferedimage(newW,newH,BufferedImage.TYPE\u INT\u BGR);
final Graphics2D g2d=image.createGraphics();
g2d.drawImage(thumbnailImage,0,0,null);
g2d.dispose();
write(image,“jpeg”,target.toFile());
返回target.toAbsolutionPath();}
我已经用下面的代码成功地完成了 这个方法来自图书馆
public int seek(int stream_index, long min_ts, long ts, long max_ts, int flags);
参数为
- 流索引用作时基参考的流索引
- min\u ts可接受的最小时间戳
- ts目标时间戳
- 最大\u ts可接受的最大时间戳
final int success = demuxer.seek(streamIndex, 0, 700, 99999999,VideoJNI.Demuxer_SEEK_FRAME_get());