Query Video Rotation Info using FFprobe

有一些通过手持设备录制的视频会把视频的旋转信息作为一个额外的字段放入视频的元数据中(比如 iOS);在对 这些视频进行处理的时候,其元数据中的宽高信息就需要使用旋转信息进行修正。

使用 ffprobe 获取原视频中的旋转信息的命令如下:

ffprobe -loglevel error -hide_banner -select_streams v -show_entries stream_tags=rotate -of json=compact=1 input.avi

查询得到的视频旋转信息是一个整型的旋转角度值(而不是弧度);取值范围为 [0, 360],常见的取值有 90/180/270 。

假定一个原视频通过 ffprobe 提取的宽高信息为 800x600,若旋转信息为 90,则实际的视频宽高为 600x800。

Query Key-Frame Info from Video Stream using FFprobe

使用 ffprobe 获取视频中的关键帧信息命令如下:

ffprobe -loglevel error -hide_banner -select_streams v -skip_frame nokey -show_frames -show_entries frame=pict_type -of json=compact=1 input.avi
ffprobe -loglevel error -hide_banner -select_streams v -show_format -show_frames -show_entries frame=pict_t ype:format=filename,duration,size:format_tags= -show_streams -of json=compact=1 input.mp4

ffprobe 的更多用法请参考其文档

一次由于线上 MySQL 并发抢占更新冲突引发的 BUG

前几天在处理线上问题的时候,发现了一个由于多客户端并发使用 CAS 去更新相同记录而导致的锁冲突,引发了数据库管理系统的慢查询累积报警。慢查询导致连接数增加,并引起插入和更新操作被堵塞,引起少量的业务堆积。

一图胜千言。

mysql_stats.all

虽然定位并解决了问题,但还是需要事后总结一下,以资后鉴。

Ffmpeg -vsync 使用场景辨析

在使用 Ffmpeg 进行视频抽帧时,发现 -vsync 参数的意思理解的不是很清楚。本文通过不同的场景 使用结果对比来辨析 -vsync 选项的枚举参数值的区别。

以下是 Ffmpeg 官网上关于 -vsync 的全部说明:

-vsync parameter

    Video sync method. For compatibility reasons old values can be specified as numbers. Newly added values will have to be specified as strings always.

    0, passthrough
        Each frame is passed with its timestamp from the demuxer to the muxer.
    1, cfr
        Frames will be duplicated and dropped to achieve exactly the requested constant frame rate.
    2, vfr
        Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp.
    drop
        As passthrough but destroys all timestamps, making the muxer generate fresh timestamps based on frame-rate.
    -1, auto
        Chooses between 1 and 2 depending on muxer capabilities. This is the default method.

    Note that the timestamps may be further modified by the muxer, after this. For example, in the case that the format option avoid_negative_ts is enabled.

    With -map you can select from which stream the timestamps should be taken. You can leave either video or audio unchanged and sync the remaining stream(s) to the unchanged one.

Ffmpeg snapshot/thumbnail 快照套路总结

使用 Ffmpeg 对视频进行抽帧操作,即把视频中感兴趣的帧输出为图片;该操作也经常被称之为视频快照、视频截图等。

视频抽帧按照输出文件的格式不同,可以输出为 jpgpnggifwebp 等格式文件。

视频抽帧按照选取视频帧的条件不同,可以分为按类型、按时间、按场景变化等不同的套路。

本文从以上两个方面汇总使用 Ffmpeg 抽帧的套路。

Generating HLS/M3U8 Using FFmpeg

FFmpeg 是开源的音视频处理项目,以使用灵活、功能丰富著称,被各大互联网公司用来构建多媒体服务的基础。

最近的项目中需要提供音视频多码率转码支持,集中调研了 FFmpegApple HTTP Live Streaming (HLS) 的支持,总结一下,遂成本文。

说明:本文中使用的命令行 ffmpeg 版本为:

 ~  ffmpeg
ffmpeg version n4.1.3 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.1 (GCC) 20181127
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora
--enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-omx --enable-shared --enable-version3
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100

Java try-catch and AssertionError

Java 的异常处理机制是 try-catch-finally 。被调用的方法或代码块可以抛出异常(Throwable,含 Exception 和 Error);被调用的方法或代码块被包含在 try 块中;catch 块中会根据具体的异常类型来实现相关的逻辑;finally 块中实现无论是否发生异常都需要的逻辑。

异常处理机制很简单;但是怎么设计异常处理方式是有一些坑的。

有一个线上服务在更新逻辑上线时,触发了一个错误处理异常的 BUG,现简单记录之。

一次由于滥用 OptionalLong.orElse 引发的 BUG

JDK 8 引入了 Optional 的概念,以解决 null 可能引发的可能的 BUG。新的类型 java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalDoublejava.util.OptionalDouble 能够有效避免 null 值的使用,强制使用者去处理 absent & present 的不同情况。

在 Vert.x 项目中集成使用 Guice 依赖注入

本文介绍了项目中在基于 Eclipse Vert.x 的 Verticle 中使用 Google Guice 进行依赖注入的实践,主要的思路是在 io.vertx.core.Verticle#start 方法中主动创建 com.google.inject.Injector 注入器实例并实行注入操作,在注入操作成功结束之后再进行后续的操作。

在开发结束后的某一天,通过万能的搜索发现已经有人提供了基于 Google GuiceEclipse Vert.x 扩展: Vert.x Guice ExtensionVert.x Guice Extension 扩展了 Vert.x 内置的 io.vertx.core.spi.VerticleFactory 机制,能够使用 SPI 的方式加载需要的 Guice 依赖。

本文总结一下自己的实现思路,然后分析 Vert.x Guice Extension 的实现细节,希望能提高自己的代码水平。