refactor: FFmpeg 7.1 support (#101)
* feat: FFmpeg 7.1 * test: reset golden * fix encoder * test: update golden files
This commit is contained in:
parent
1b26cf82f8
commit
d01256b982
35 changed files with 73 additions and 65 deletions
19
.github/workflows/test.yml
vendored
19
.github/workflows/test.yml
vendored
|
|
@ -13,17 +13,17 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CGO_CFLAGS_ALLOW: -Xpreprocessor
|
CGO_CFLAGS_ALLOW: -Xpreprocessor
|
||||||
VIPS_VERSION: 8.17.1
|
VIPS_VERSION: 8.17.1
|
||||||
FFMPEG_VERSION: 5.1.2
|
FFMPEG_VERSION: 7.1.1
|
||||||
V: 4
|
V: 5
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24
|
||||||
|
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install linux dependencies
|
- name: Install linux dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -38,7 +38,7 @@ jobs:
|
||||||
libopenslide-dev libcfitsio-dev liborc-0.4-dev libpango1.0-dev \
|
libopenslide-dev libcfitsio-dev liborc-0.4-dev libpango1.0-dev \
|
||||||
libtiff5-dev libgsf-1-dev giflib-tools libwebp-dev \
|
libtiff5-dev libgsf-1-dev giflib-tools libwebp-dev \
|
||||||
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
|
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
|
||||||
librtmp-dev libvorbis-dev \
|
librtmp-dev libvorbis-dev libdav1d-dev libaom-dev \
|
||||||
libopenjp2-7-dev libcgif-dev
|
libopenjp2-7-dev libcgif-dev
|
||||||
# Install newer libheif from backports
|
# Install newer libheif from backports
|
||||||
sudo apt-get install -y -t jammy-backports libheif-dev || sudo apt-get install -y libheif-dev
|
sudo apt-get install -y -t jammy-backports libheif-dev || sudo apt-get install -y libheif-dev
|
||||||
|
|
@ -78,13 +78,12 @@ jobs:
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-ffmpeg-${{ env.V }}-
|
${{ runner.os }}-ffmpeg-${{ env.V }}-
|
||||||
|
|
||||||
|
|
||||||
- name: Build ffmpeg from source
|
- name: Build ffmpeg from source
|
||||||
run: |
|
run: |
|
||||||
if [ ! -d "ffmpeg-${{ env.FFMPEG_VERSION }}" ]
|
if [ ! -d "ffmpeg-${{ env.FFMPEG_VERSION }}" ]
|
||||||
then
|
then
|
||||||
wget https://ffmpeg.org/releases/ffmpeg-${{ env.FFMPEG_VERSION }}.tar.bz2
|
wget https://ffmpeg.org/releases/ffmpeg-${{ env.FFMPEG_VERSION }}.tar.xz
|
||||||
tar jvxf ffmpeg-${{ env.FFMPEG_VERSION }}.tar.bz2
|
tar xf ffmpeg-${{ env.FFMPEG_VERSION }}.tar.xz
|
||||||
fi
|
fi
|
||||||
cd ffmpeg-${{ env.FFMPEG_VERSION }}
|
cd ffmpeg-${{ env.FFMPEG_VERSION }}
|
||||||
./configure --prefix=/usr/local \
|
./configure --prefix=/usr/local \
|
||||||
|
|
@ -101,7 +100,9 @@ jobs:
|
||||||
--enable-libwebp \
|
--enable-libwebp \
|
||||||
--enable-libvpx \
|
--enable-libvpx \
|
||||||
--enable-libx265 \
|
--enable-libx265 \
|
||||||
--enable-libx264
|
--enable-libx264 \
|
||||||
|
--enable-libdav1d \
|
||||||
|
--enable-libaom
|
||||||
make && sudo make install
|
make && sudo make install
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
|
|
||||||
|
|
|
||||||
15
Dockerfile
15
Dockerfile
|
|
@ -1,14 +1,13 @@
|
||||||
ARG GOLANG_VERSION=1.24.5
|
ARG GOLANG_VERSION=1.24.5
|
||||||
FROM golang:${GOLANG_VERSION}-bookworm as builder
|
FROM golang:${GOLANG_VERSION}-bookworm as builder
|
||||||
|
|
||||||
ARG FFMPEG_VERSION=5.1.2
|
ARG FFMPEG_VERSION=7.1.1
|
||||||
ARG VIPS_VERSION=8.17.1
|
ARG VIPS_VERSION=8.17.1
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||||
ENV MAKEFLAGS="-j8"
|
ENV MAKEFLAGS="-j8"
|
||||||
|
|
||||||
|
|
||||||
# Installs libvips + required libraries
|
# Installs libvips + required libraries
|
||||||
RUN DEBIAN_FRONTEND=noninteractive \
|
RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
|
|
@ -21,7 +20,7 @@ RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
swig libpango1.0-dev libmatio-dev libopenslide-dev libcfitsio-dev libopenjp2-7-dev \
|
swig libpango1.0-dev libmatio-dev libopenslide-dev libcfitsio-dev libopenjp2-7-dev \
|
||||||
libgsf-1-dev libfftw3-dev liborc-0.4-dev librsvg2-dev libimagequant-dev libaom-dev libheif-dev \
|
libgsf-1-dev libfftw3-dev liborc-0.4-dev librsvg2-dev libimagequant-dev libaom-dev libheif-dev \
|
||||||
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
|
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
|
||||||
libspng-dev libcgif-dev librtmp-dev libvorbis-dev && \
|
libspng-dev libcgif-dev librtmp-dev libvorbis-dev libdav1d-dev && \
|
||||||
cd /tmp && \
|
cd /tmp && \
|
||||||
curl -fsSLO https://github.com/libvips/libvips/releases/download/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz && \
|
curl -fsSLO https://github.com/libvips/libvips/releases/download/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz && \
|
||||||
tar xf vips-${VIPS_VERSION}.tar.xz && \
|
tar xf vips-${VIPS_VERSION}.tar.xz && \
|
||||||
|
|
@ -36,8 +35,8 @@ RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
ninja -C _build && \
|
ninja -C _build && \
|
||||||
ninja -C _build install && \
|
ninja -C _build install && \
|
||||||
cd /tmp && \
|
cd /tmp && \
|
||||||
curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz && \
|
||||||
tar jvxf ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
|
tar xf ffmpeg-${FFMPEG_VERSION}.tar.xz && \
|
||||||
cd /tmp/ffmpeg-${FFMPEG_VERSION} && \
|
cd /tmp/ffmpeg-${FFMPEG_VERSION} && \
|
||||||
./configure --prefix=/usr/local \
|
./configure --prefix=/usr/local \
|
||||||
--disable-debug \
|
--disable-debug \
|
||||||
|
|
@ -53,7 +52,9 @@ RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
--enable-libwebp \
|
--enable-libwebp \
|
||||||
--enable-libvpx \
|
--enable-libvpx \
|
||||||
--enable-libx265 \
|
--enable-libx265 \
|
||||||
--enable-libx264 && \
|
--enable-libx264 \
|
||||||
|
--enable-libdav1d \
|
||||||
|
--enable-libaom && \
|
||||||
make && make install && \
|
make && make install && \
|
||||||
ldconfig && \
|
ldconfig && \
|
||||||
rm -rf /usr/local/lib/python* && \
|
rm -rf /usr/local/lib/python* && \
|
||||||
|
|
@ -89,7 +90,7 @@ RUN echo "deb http://deb.debian.org/debian bookworm-backports main" > /etc/apt/s
|
||||||
libpango1.0-0 libmatio11 libopenslide0 libopenjp2-7 libjemalloc2 \
|
libpango1.0-0 libmatio11 libopenslide0 libopenjp2-7 libjemalloc2 \
|
||||||
libgsf-1-114 libfftw3-bin liborc-0.4-0 librsvg2-2 libcfitsio10 libimagequant0 libaom3 \
|
libgsf-1-114 libfftw3-bin liborc-0.4-0 librsvg2-2 libcfitsio10 libimagequant0 libaom3 \
|
||||||
libx264-dev libx265-dev libnuma-dev libvpx7 libtheora0 libvorbis-dev \
|
libx264-dev libx265-dev libnuma-dev libvpx7 libtheora0 libvorbis-dev \
|
||||||
libspng0 libcgif0 && \
|
libspng0 libcgif0 libdav1d6 && \
|
||||||
apt-get install --no-install-recommends -y -t bookworm-backports libheif1 && \
|
apt-get install --no-install-recommends -y -t bookworm-backports libheif1 && \
|
||||||
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
|
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
|
||||||
apt-get autoremove -y && \
|
apt-get autoremove -y && \
|
||||||
|
|
|
||||||
|
|
@ -210,23 +210,28 @@ AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha) {
|
||||||
return output_frame;
|
return output_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPacket create_packet() {
|
AVPacket *create_packet() {
|
||||||
AVPacket *pkt = av_packet_alloc();
|
AVPacket *pkt = av_packet_alloc();
|
||||||
|
if (!pkt) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pkt->data = NULL;
|
pkt->data = NULL;
|
||||||
pkt->size = 0;
|
pkt->size = 0;
|
||||||
return *pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame) {
|
||||||
obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame) {
|
|
||||||
int err = 0, retry = 0;
|
int err = 0, retry = 0;
|
||||||
if (!(*frame) && !(*frame = av_frame_alloc())) {
|
if (!(*frame) && !(*frame = av_frame_alloc())) {
|
||||||
err = AVERROR(ENOMEM);
|
err = AVERROR(ENOMEM);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to receive a frame from the decoder first
|
||||||
if ((err = avcodec_receive_frame(dec_ctx, *frame)) != AVERROR(EAGAIN)) {
|
if ((err = avcodec_receive_frame(dec_ctx, *frame)) != AVERROR(EAGAIN)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((err = av_read_frame(fmt_ctx, pkt)) < 0) {
|
if ((err = av_read_frame(fmt_ctx, pkt)) < 0) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -239,6 +244,7 @@ obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_
|
||||||
if (retry++ >= 10) {
|
if (retry++ >= 10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
av_packet_unref(pkt);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(*frame) && !(*frame = av_frame_alloc())) {
|
if (!(*frame) && !(*frame = av_frame_alloc())) {
|
||||||
|
|
@ -251,7 +257,7 @@ obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_
|
||||||
}
|
}
|
||||||
av_packet_unref(pkt);
|
av_packet_unref(pkt);
|
||||||
}
|
}
|
||||||
if (pkt->buf) {
|
if (pkt->data) {
|
||||||
av_packet_unref(pkt);
|
av_packet_unref(pkt);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -301,8 +301,13 @@ func populateFrames(av *AVContext, frames <-chan *C.AVFrame) <-chan struct{} {
|
||||||
|
|
||||||
func createThumbContext(av *AVContext, maxFrames C.int) error {
|
func createThumbContext(av *AVContext, maxFrames C.int) error {
|
||||||
pkt := C.create_packet()
|
pkt := C.create_packet()
|
||||||
|
if pkt == nil {
|
||||||
|
return avError(C.int(ErrNoMem))
|
||||||
|
}
|
||||||
|
defer C.av_packet_free(&pkt)
|
||||||
|
|
||||||
var frame *C.AVFrame
|
var frame *C.AVFrame
|
||||||
err := C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame)
|
err := C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, pkt, &frame)
|
||||||
if err >= 0 {
|
if err >= 0 {
|
||||||
incrementDuration(av, frame, 0)
|
incrementDuration(av, frame, 0)
|
||||||
av.thumbContext = C.create_thumb_context(av.stream, frame)
|
av.thumbContext = C.create_thumb_context(av.stream, frame)
|
||||||
|
|
@ -311,9 +316,6 @@ func createThumbContext(av *AVContext, maxFrames C.int) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err < 0 {
|
if err < 0 {
|
||||||
if pkt.buf != nil {
|
|
||||||
C.av_packet_unref(&pkt)
|
|
||||||
}
|
|
||||||
if frame != nil {
|
if frame != nil {
|
||||||
C.av_frame_free(&frame)
|
C.av_frame_free(&frame)
|
||||||
}
|
}
|
||||||
|
|
@ -332,18 +334,20 @@ func createThumbContext(av *AVContext, maxFrames C.int) error {
|
||||||
frames := make(chan *C.AVFrame, n)
|
frames := make(chan *C.AVFrame, n)
|
||||||
done := populateFrames(av, frames)
|
done := populateFrames(av, frames)
|
||||||
frames <- frame
|
frames <- frame
|
||||||
if pkt.buf != nil {
|
|
||||||
C.av_packet_unref(&pkt)
|
|
||||||
}
|
|
||||||
return populateThumbContext(av, frames, n, done)
|
return populateThumbContext(av, frames, n, done)
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <-chan struct{}) error {
|
func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <-chan struct{}) error {
|
||||||
pkt := C.create_packet()
|
pkt := C.create_packet()
|
||||||
|
if pkt == nil {
|
||||||
|
return avError(C.int(ErrNoMem))
|
||||||
|
}
|
||||||
|
defer C.av_packet_free(&pkt)
|
||||||
|
|
||||||
var frame *C.AVFrame
|
var frame *C.AVFrame
|
||||||
var err C.int
|
var err C.int
|
||||||
for i := C.int(1); i < n; i++ {
|
for i := C.int(1); i < n; i++ {
|
||||||
err = C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame)
|
err = C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, pkt, &frame)
|
||||||
if err < 0 {
|
if err < 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -362,9 +366,6 @@ func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <
|
||||||
av.selectedIndex = av.availableIndex
|
av.selectedIndex = av.availableIndex
|
||||||
}
|
}
|
||||||
close(frames)
|
close(frames)
|
||||||
if pkt.buf != nil {
|
|
||||||
C.av_packet_unref(&pkt)
|
|
||||||
}
|
|
||||||
if frame != nil {
|
if frame != nil {
|
||||||
C.av_frame_free(&frame)
|
C.av_frame_free(&frame)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,9 @@ int create_codec_context(AVStream *video_stream, AVCodecContext **dec_ctx);
|
||||||
|
|
||||||
AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha);
|
AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha);
|
||||||
|
|
||||||
AVPacket create_packet();
|
AVPacket *create_packet();
|
||||||
|
|
||||||
int
|
int obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame);
|
||||||
obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame);
|
|
||||||
|
|
||||||
ThumbContext *create_thumb_context(AVStream *stream, AVFrame *frame);
|
ThumbContext *create_thumb_context(AVStream *stream, AVFrame *frame);
|
||||||
|
|
||||||
|
|
|
||||||
2
testdata/golden/meta/macabre.mp4-1.meta.json
vendored
2
testdata/golden/meta/macabre.mp4-1.meta.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
2
testdata/golden/meta/macabre.mp4-5.meta.json
vendored
2
testdata/golden/meta/macabre.mp4-5.meta.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
2
testdata/golden/meta/macabre.mp4.meta.json
vendored
2
testdata/golden/meta/macabre.mp4.meta.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
2
testdata/golden/meta/schizo_0.mp4.meta.json
vendored
2
testdata/golden/meta/schizo_0.mp4.meta.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
2
testdata/golden/meta/schizo_90.mp4.meta.json
vendored
2
testdata/golden/meta/schizo_90.mp4.meta.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue