到目前为止,我已经成功地通过以下方法从视频中拍摄了快照。
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(); }
已尝试使用“Demuxer”-s seek 方法,但没有运气。
最佳答案
我已经用下面的代码成功地做到了
图书馆的方法
public int seek(int stream_index, long min_ts, long ts, long max_ts, int flags);
参数是我的实现是
final int success = demuxer.seek(streamIndex, 0, 700, 99999999,VideoJNI.Demuxer_SEEK_FRAME_get());
关于java - Humble Video 拍摄给定时间的快照,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67656157/