java - Humble Video 拍摄给定时间的快照

标签 java video ffmpeg

  • 你好,我用的是https://github.com/artclarke/humble-video从视频中获取缩略图。
    到目前为止,我已经成功地通过以下方法从视频中拍摄了快照。
    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(); }
    
  • 现在,我想做的是在视频开始后 2 秒后拍摄快照,这可能吗?我
    已尝试使用“Demuxer”-s seek 方法,但没有运气。
  • 最佳答案

    我已经用下面的代码成功地做到了
    图书馆的方法

    public int seek(int stream_index, long min_ts, long ts, long max_ts, int flags);
    
    参数是
  • 流索引 用作时基引用的流的索引
  • min_ts 可接受的最小时间戳
  • ts 目标时间戳
  • max_ts 可接受的最大时间戳

  • 我的实现是
    final int success = demuxer.seek(streamIndex, 0, 700, 99999999,VideoJNI.Demuxer_SEEK_FRAME_get());
    

    关于java - Humble Video 拍摄给定时间的快照,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67656157/

    相关文章:

    java - 如何通过Jsoup获取 "select"html元素?

    java - 我试图在这里移动 SDK 中获取手势,但不明白要传递给手势方法的内容是什么?如何解决这个问题

    html - 如何在 WebRTC 中使用 FFmpeg H264 编码器?

    javascript - 使 Youtube 360​​ 度视频在移动设备上运行

    Android 音频 RTMP 发布

    java - TextView.mText 值已更改但未在输出窗口中更新

    java - 防止 JAXB XML 解析上的循环引用

    android - 在浏览器跨设备中播放视频

    android - 将 FFmpeg 与 Android-NDK 一起使用

    audio - 如何转换音频并跟踪所有格式的元数据