diff --git a/Dockerfile b/Dockerfile index 184948d..eddff2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -71,7 +71,6 @@ RUN go mod download COPY . . -RUN if [ "$TARGETARCH" = "amd64" ]; then go test ./...; fi RUN go build -o ${GOPATH}/bin/imagorvideo ./cmd/imagorvideo/main.go FROM debian:bookworm-slim diff --git a/cmd/imagorvideo/main.go b/cmd/imagorvideo/main.go index 3c87657..01bab1a 100644 --- a/cmd/imagorvideo/main.go +++ b/cmd/imagorvideo/main.go @@ -1,6 +1,7 @@ package main import ( + imagorvideoextended "git.cef.icu/CEF/imagorextended" "github.com/cshum/imagor/config" "github.com/cshum/imagor/config/awsconfig" "github.com/cshum/imagor/config/gcloudconfig" @@ -12,6 +13,7 @@ import ( func main() { var server = config.CreateServer( os.Args[1:], + imagorvideoextended.Config, imagorvideo.Config, vipsconfig.WithVips, awsconfig.WithAWS, diff --git a/config.go b/config.go index 46d28f3..206368b 100644 --- a/config.go +++ b/config.go @@ -1,4 +1,4 @@ -package imagorvideo +package imagorvideoextended import ( "flag" @@ -9,14 +9,10 @@ import ( // Config imagorvideo config.Option func Config(fs *flag.FlagSet, cb func() (*zap.Logger, bool)) imagor.Option { var ( - ffmpegFallbackImage = fs.String("ffmpeg-fallback-image", "", - "FFmpeg fallback image on processing error. Supports image path enabled by loaders or storages") - logger, isDebug = cb() ) return imagor.WithProcessors( NewProcessor( - WithFallbackImage(*ffmpegFallbackImage), WithLogger(logger), WithDebug(isDebug), ), diff --git a/config_test.go b/config_test.go index c326014..92da3be 100644 --- a/config_test.go +++ b/config_test.go @@ -1,4 +1,4 @@ -package imagorvideo +package imagorvideoextended import ( "github.com/cshum/imagor" diff --git a/ffmpeg/callback.go b/ffmpeg/callback.go deleted file mode 100644 index 24e7fdf..0000000 --- a/ffmpeg/callback.go +++ /dev/null @@ -1,55 +0,0 @@ -package ffmpeg - -// #include "ffmpeg.h" -import "C" -import ( - "github.com/cshum/imagor/vips/pointer" - "io" - "reflect" - "unsafe" -) - -//export goPacketRead -func goPacketRead(opaque unsafe.Pointer, buffer *C.uint8_t, bufSize C.int) C.int { - ctx, ok := pointer.Restore(opaque).(*AVContext) - if !ok || ctx.reader == nil { - return C.int(ErrUnknown) - } - size := int(bufSize) - sh := &reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(buffer)), - Len: size, - Cap: size, - } - buf := *(*[]byte)(unsafe.Pointer(sh)) - n, err := ctx.reader.Read(buf) - if err == io.EOF { - if n == 0 { - return C.int(ErrEOF) - } - } else if err != nil { - return C.int(ErrUnknown) - } - return C.int(n) -} - -//export goPacketSeek -func goPacketSeek(opaque unsafe.Pointer, offset C.int64_t, whence C.int) C.int64_t { - ctx, ok := pointer.Restore(opaque).(*AVContext) - if !ok || ctx.seeker == nil { - return C.int64_t(ErrUnknown) - } - if whence == C.AVSEEK_SIZE { - return C.int64_t(ctx.size) - } - n, err := ctx.seeker.Seek(int64(offset), int(whence)) - if err != nil { - return C.int64_t(ErrUnknown) - } - return C.int64_t(n) -} - -//export goAVLoggingHandler -func goAVLoggingHandler(level C.int, cstr *C.char) { - log(AVLogLevel(level), C.GoString(cstr)) -} diff --git a/ffmpeg/errors.go b/ffmpeg/errors.go deleted file mode 100644 index 0ffd823..0000000 --- a/ffmpeg/errors.go +++ /dev/null @@ -1,38 +0,0 @@ -package ffmpeg - -// #include "ffmpeg.h" -import "C" - -type avError int - -// AV Error enum -const ( - ErrNoMem = avError(-C.ENOMEM) - ErrEOF = avError(C.AVERROR_EOF) - ErrUnknown = avError(C.AVERROR_UNKNOWN) - ErrDecoderNotFound = avError(C.AVERROR_DECODER_NOT_FOUND) - ErrInvalidData = avError(C.AVERROR_INVALIDDATA) - ErrTooBig = avError(C.ERR_TOO_BIG) -) - -func (e avError) errorString() string { - switch e { - case ErrNoMem: - return "cannot allocate memory" - case ErrTooBig: - return "video or cover art size exceeds maximum allowed dimensions" - case ErrEOF: - return "end of file" - case ErrDecoderNotFound: - return "decoder not found" - case ErrInvalidData: - return "invalid data found when processing input" - default: - return "unknown error occurred" - } -} - -// Error implements error interface -func (e avError) Error() string { - return "ffmpeg: " + e.errorString() -} diff --git a/ffmpeg/errors_test.go b/ffmpeg/errors_test.go deleted file mode 100644 index 3b0d483..0000000 --- a/ffmpeg/errors_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package ffmpeg - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestErrors(t *testing.T) { - assert.Equal(t, "ffmpeg: cannot allocate memory", ErrNoMem.Error()) - assert.Equal(t, "ffmpeg: end of file", ErrEOF.Error()) - assert.Equal(t, "ffmpeg: unknown error occurred", ErrUnknown.Error()) - assert.Equal(t, "ffmpeg: decoder not found", ErrDecoderNotFound.Error()) - assert.Equal(t, "ffmpeg: invalid data found when processing input", ErrInvalidData.Error()) - assert.Equal(t, "ffmpeg: video or cover art size exceeds maximum allowed dimensions", ErrTooBig.Error()) -} diff --git a/ffmpeg/ffmpeg.c b/ffmpeg/ffmpeg.c deleted file mode 100644 index 2e5db34..0000000 --- a/ffmpeg/ffmpeg.c +++ /dev/null @@ -1,413 +0,0 @@ -#include "ffmpeg.h" - -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -void free_format_context(AVFormatContext *fmt_ctx) { - if (!fmt_ctx) { - return; - } - av_free(fmt_ctx->pb->buffer); - avio_context_free(&fmt_ctx->pb); - avformat_close_input(&fmt_ctx); -} - -int allocate_format_context(AVFormatContext **fmt_ctx) { - AVFormatContext *ctx = NULL; - if (!(ctx = avformat_alloc_context())) { - return AVERROR(ENOMEM); - } - *fmt_ctx = ctx; - return 0; -} - -int create_format_context(AVFormatContext *fmt_ctx, void* opaque, int flags) { - int err = 0; - uint8_t *avio_buffer = NULL; - AVIOContext *avio_ctx = NULL; - if (!(avio_buffer = av_malloc(BUFFER_SIZE))) { - avformat_free_context(fmt_ctx); - return AVERROR(ENOMEM); - } - void *reader = NULL; - void *seeker = NULL; - int write_flag = 0; - int seekable = 0; - if (flags & READ_PACKET_FLAG) { - reader = goPacketRead; - } - if (flags & SEEK_PACKET_FLAG) { - seeker = goPacketSeek; - seekable = 1; - } - if (!(avio_ctx = avio_alloc_context(avio_buffer, BUFFER_SIZE, write_flag, opaque, reader, NULL, seeker))) { - av_free(avio_buffer); - avformat_free_context(fmt_ctx); - return AVERROR(ENOMEM); - } - fmt_ctx->pb = avio_ctx; - fmt_ctx->pb->seekable = seekable; - err = avformat_open_input(&fmt_ctx, NULL, NULL, NULL); - if (err < 0) { - av_free(avio_ctx->buffer); - avio_context_free(&avio_ctx); - free_format_context(fmt_ctx); - return err; - } - err = pthread_mutex_lock(&mutex); - if (err < 0) { - free_format_context(fmt_ctx); - return err; - } - err = avformat_find_stream_info(fmt_ctx, NULL); - int muErr = pthread_mutex_unlock(&mutex); - if (err < 0 || muErr < 0) { - free_format_context(fmt_ctx); - if (muErr < 0) { - return muErr; - } - } - return err; -} - -static int get_orientation(AVStream *video_stream) { - uint8_t *display_matrix = av_stream_get_side_data(video_stream, AV_PKT_DATA_DISPLAYMATRIX, NULL); - double theta = 0; - if (display_matrix) { - theta = -av_display_rotation_get((int32_t *) display_matrix); - } - - theta -= 360 * floor(theta / 360 + 0.9 / 360); - - int rot = (int) (90 * round(theta / 90)) % 360; - - switch (rot) { - case 90: - return 6; - case 180: - return 3; - case 270: - return 8; - default: - return 1; - }; -} - -void get_metadata(AVFormatContext *fmt_ctx, char **artist, char **title) { - AVDictionaryEntry *tag = NULL; - if ((tag = av_dict_get(fmt_ctx->metadata, "artist", NULL, 0))) { - *artist = tag->value; - } - if ((tag = av_dict_get(fmt_ctx->metadata, "title", NULL, 0))) { - *title = tag->value; - } -} - -int find_streams(AVFormatContext *fmt_ctx, AVStream **video_stream, int *orientation) { - int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); - int audio_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); - int video_audio = 0; - if (audio_stream_index >= 0) { - video_audio |= HAS_AUDIO_STREAM; - } - if (video_stream_index >= 0) { - video_audio |= HAS_VIDEO_STREAM; - } else { - if (video_audio) { - return video_audio; - } - return AVERROR_STREAM_NOT_FOUND; - } - *video_stream = fmt_ctx->streams[video_stream_index]; - *orientation = get_orientation(*video_stream); - return video_audio; -} - -static int open_codec(AVCodecContext *codec_ctx, AVCodec *codec) { - int err = pthread_mutex_lock(&mutex); - if (err < 0) { - return err; - } - err = avcodec_open2(codec_ctx, codec, NULL); - int muErr = pthread_mutex_unlock(&mutex); - if (muErr < 0) { - return muErr; - } - return err; -} - -int create_codec_context(AVStream *video_stream, AVCodecContext **dec_ctx) { - AVCodec *dec = NULL; - AVCodecParameters *par = video_stream->codecpar; - if (par->codec_id == AV_CODEC_ID_VP8) { - dec = avcodec_find_decoder_by_name("libvpx"); - } else if (par->codec_id == AV_CODEC_ID_VP9) { - dec = avcodec_find_decoder_by_name("libvpx-vp9"); - } - if (!dec) { - dec = avcodec_find_decoder(par->codec_id); - } - if (dec == NULL) { - return AVERROR_DECODER_NOT_FOUND; - } - if (par->format == -1) { - return AVERROR_INVALIDDATA; - } - if (av_get_bits_per_pixel(av_pix_fmt_desc_get(par->format)) * par->height * par->width > 1 << 30) { - return ERR_TOO_BIG; - } - if (!(*dec_ctx = avcodec_alloc_context3(dec))) { - return AVERROR(ENOMEM); - } - int err = avcodec_parameters_to_context(*dec_ctx, par); - if (err < 0) { - avcodec_free_context(dec_ctx); - return err; - } - err = open_codec(*dec_ctx, dec); - if (err < 0) { - avcodec_free_context(dec_ctx); - } - return err; -} - -AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha) { - int output_fmt = alpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24; - struct SwsContext *sws_ctx = NULL; - AVFrame *output_frame = av_frame_alloc(); - if (!output_frame) { - return output_frame; - } - output_frame->height = frame->height; - output_frame->width = frame->width; - output_frame->format = output_fmt; - if (av_frame_get_buffer(output_frame, 1) < 0) { - goto free; - } - if (output_fmt == frame->format) { - if (av_frame_copy(output_frame, frame) < 0) { - goto free; - } - goto done; - } - sws_ctx = sws_getContext(frame->width, frame->height, frame->format, - output_frame->width, output_frame->height, output_fmt, - SWS_LANCZOS | SWS_ACCURATE_RND, NULL, NULL, NULL); - if (!sws_ctx) { - goto free; - } - if (sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0, frame->height, output_frame->data, - output_frame->linesize) != output_frame->height) { - goto free; - } else { - goto done; - } - free: - av_frame_free(&output_frame); - done: - if (sws_ctx) { - sws_freeContext(sws_ctx); - } - return output_frame; -} - -AVPacket create_packet() { - AVPacket *pkt = av_packet_alloc(); - pkt->data = NULL; - pkt->size = 0; - return *pkt; -} - -int -obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame) { - int err = 0, retry = 0; - if (!(*frame) && !(*frame = av_frame_alloc())) { - err = AVERROR(ENOMEM); - return err; - } - if ((err = avcodec_receive_frame(dec_ctx, *frame)) != AVERROR(EAGAIN)) { - return err; - } - while (1) { - if ((err = av_read_frame(fmt_ctx, pkt)) < 0) { - break; - } - if (pkt->stream_index != stream_index) { - av_packet_unref(pkt); - continue; - } - if ((err = avcodec_send_packet(dec_ctx, pkt)) < 0) { - if (retry++ >= 10) { - break; - } - continue; - } - if (!(*frame) && !(*frame = av_frame_alloc())) { - err = AVERROR(ENOMEM); - break; - } - err = avcodec_receive_frame(dec_ctx, *frame); - if (err >= 0 || err != AVERROR(EAGAIN)) { - break; - } - av_packet_unref(pkt); - } - if (pkt->buf) { - av_packet_unref(pkt); - } - return err; -} - -ThumbContext *create_thumb_context(AVStream *stream, AVFrame *frame) { - ThumbContext *thumb_ctx = av_mallocz(sizeof *thumb_ctx); - if (!thumb_ctx) { - return thumb_ctx; - } - thumb_ctx->desc = av_pix_fmt_desc_get(frame->format); - int nb_frames = 100; - if (stream->disposition & AV_DISPOSITION_ATTACHED_PIC) { - nb_frames = 1; - } else if (stream->nb_frames && stream->nb_frames < 400) { - nb_frames = (int) (stream->nb_frames >> 2) + 1; - } - int frames_in_128mb = (1 << 30) / (av_get_bits_per_pixel(thumb_ctx->desc) * frame->height * frame->width); - thumb_ctx->max_frames = FFMIN(nb_frames, frames_in_128mb); - int i; - for (i = 0; i < thumb_ctx->desc->nb_components; i++) { - thumb_ctx->hist_size += 1 << thumb_ctx->desc->comp[i].depth; - } - thumb_ctx->median = av_calloc(thumb_ctx->hist_size, sizeof(double)); - if (!thumb_ctx->median) { - av_free(thumb_ctx); - return NULL; - } - thumb_ctx->frames = av_malloc_array((size_t) thumb_ctx->max_frames, sizeof *thumb_ctx->frames); - if (!thumb_ctx->frames) { - av_free(thumb_ctx->median); - av_free(thumb_ctx); - return NULL; - } - for (i = 0; i < thumb_ctx->max_frames; i++) { - thumb_ctx->frames[i].frame = NULL; - thumb_ctx->frames[i].hist = av_calloc(thumb_ctx->hist_size, sizeof(int)); - if (!thumb_ctx->frames[i].hist) { - for (i--; i >= 0; i--) { - av_free(thumb_ctx->frames[i].hist); - } - av_free(thumb_ctx->median); - av_free(thumb_ctx); - return NULL; - } - } - return thumb_ctx; -} - -void free_thumb_context(ThumbContext *thumb_ctx) { - if (!thumb_ctx) { - return; - } - int i; - for (i = 0; i < thumb_ctx->n; i++) { - av_frame_free(&thumb_ctx->frames[i].frame); - av_free(thumb_ctx->frames[i].hist); - } - for (i = thumb_ctx->n; i < thumb_ctx->max_frames; i++) { - av_free(thumb_ctx->frames[i].hist); - } - av_free(thumb_ctx->median); - av_free(thumb_ctx->frames); - av_free(thumb_ctx); -} - -static double root_mean_square_error(const int *hist, const double *median, size_t hist_size) { - int i; - double err, sum_sq_err = 0; - for (i = 0; i < hist_size; i++) { - err = median[i] - (double) hist[i]; - sum_sq_err += err * err; - } - return sum_sq_err; -} - -void populate_frame(ThumbContext *thumb_ctx, int n, AVFrame *frame) { - thumb_ctx->frames[n].frame = frame; -} - -void populate_histogram(ThumbContext *thumb_ctx, int n, AVFrame *frame) { - const AVPixFmtDescriptor *desc = thumb_ctx->desc; - thumb_ctx->frames[n].frame = frame; - int *hist = thumb_ctx->frames[n].hist; - AVComponentDescriptor comp; - int w, h, plane, depth, mask, shift, step, height, width; - uint64_t flags; - uint8_t **data = frame->data; - int *linesize = frame->linesize; - for (int c = 0; c < desc->nb_components; c++) { - comp = desc->comp[c]; - plane = comp.plane; - depth = comp.depth; - mask = (1 << depth) - 1; - shift = comp.shift; - step = comp.step; - flags = desc->flags; - width = !(desc->log2_chroma_w) || (c != 1 && c != 2) ? frame->width : AV_CEIL_RSHIFT(frame->width, - desc->log2_chroma_w); - height = !(desc->log2_chroma_h) || (c != 1 && c != 2) ? frame->height : AV_CEIL_RSHIFT(frame->height, - desc->log2_chroma_h); - for (h = 0; h < height; h++) { - w = width; - if (flags & AV_PIX_FMT_FLAG_BITSTREAM) { - const uint8_t *p = data[plane] + h * linesize[plane] + (comp.offset >> 3); - shift = 8 - depth - (comp.offset & 7); - - while (w--) { - int val = (*p >> shift) & mask; - shift -= step; - p -= shift >> 3; - shift &= 7; - (*(hist + val))++; - } - } else { - const uint8_t *p = data[plane] + h * linesize[plane] + comp.offset; - int is_8bit = shift + depth <= 8; - - if (is_8bit) - p += (flags & AV_PIX_FMT_FLAG_BE) != 0; - - while (w--) { - int val = is_8bit ? *p : - flags & AV_PIX_FMT_FLAG_BE ? AV_RB16(p) : AV_RL16(p); - val = (val >> shift) & mask; - p += step; - (*(hist + val))++; - } - } - } - hist += 1 << depth; - } -} - -int find_best_frame_index(ThumbContext *thumb_ctx) { - int i, j, n = 0, m = thumb_ctx->n, *hist = NULL; - double *median = thumb_ctx->median; - for (j = 0; j < m; j++) { - hist = thumb_ctx->frames[j].hist; - for (i = 0; i < thumb_ctx->hist_size; i++) { - median[i] += (double) hist[i] / m; - } - } - struct thumb_frame *t_frame = NULL; - double min_sum_sq_err = DBL_MAX, sum_sq_err = 0; - for (i = 0; i < thumb_ctx->n; i++) { - t_frame = thumb_ctx->frames + i; - sum_sq_err = root_mean_square_error(t_frame->hist, thumb_ctx->median, thumb_ctx->hist_size); - if (sum_sq_err < min_sum_sq_err) { - min_sum_sq_err = sum_sq_err; - n = i; - } - } - return n; -} - -AVFrame *select_frame(ThumbContext *thumb_ctx, int n) { - return thumb_ctx->frames[n].frame; -} \ No newline at end of file diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go deleted file mode 100644 index 497ee98..0000000 --- a/ffmpeg/ffmpeg.go +++ /dev/null @@ -1,401 +0,0 @@ -package ffmpeg - -// #cgo pkg-config: libavformat libavutil libavcodec libswscale -// #cgo CFLAGS: -std=c11 -// #cgo LDFLAGS: -lm -// #include "ffmpeg.h" -import "C" -import ( - "github.com/cshum/imagor/vips/pointer" - "io" - "math" - "time" - "unsafe" -) - -const ( - readPacketFlag = 1 - seekPacketFlag = 2 - hasVideo = 1 - hasAudio = 2 -) - -// Metadata AV metadata -type Metadata struct { - Orientation int `json:"orientation"` - Duration int `json:"duration,omitempty"` - Width int `json:"width,omitempty"` - Height int `json:"height,omitempty"` - Title string `json:"title,omitempty"` - Artist string `json:"artist,omitempty"` - FPS float64 `json:"fps,omitempty"` - HasVideo bool `json:"has_video"` - HasAudio bool `json:"has_audio"` -} - -// AVContext manages lifecycle of AV contexts and reader stream -type AVContext struct { - opaque unsafe.Pointer - reader io.Reader - seeker io.Seeker - formatContext *C.AVFormatContext - stream *C.AVStream - codecContext *C.AVCodecContext - thumbContext *C.ThumbContext - selectedIndex C.int - selectedDuration time.Duration - frame *C.AVFrame - durationInFormat bool - orientation int - size int64 - duration time.Duration - availableIndex C.int - availableDuration time.Duration - width, height int - title, artist string - hasVideo, hasAudio bool - closed bool -} - -// LoadAVContext load and create AVContext from reader stream -func LoadAVContext(reader io.Reader, size int64) (*AVContext, error) { - av := &AVContext{ - reader: reader, - size: size, - selectedIndex: -1, - } - if seeker, ok := reader.(io.Seeker); ok { - av.seeker = seeker - } - flags := C.int(readPacketFlag) - if av.seeker != nil { - flags |= seekPacketFlag - } - if err := createFormatContext(av, flags); err != nil { - return nil, err - } - if !av.hasVideo { - return av, nil - } - return av, createDecoder(av) -} - -// ProcessFrames triggers frame processing -// limit under max num of frames if maxFrames > 0 -func (av *AVContext) ProcessFrames(maxFrames int) (err error) { - if av.formatContext == nil || av.codecContext == nil { - return ErrDecoderNotFound - } - if av.thumbContext == nil { - return createThumbContext(av, C.int(maxFrames)) - } - return -} - -// SelectFrame triggers frame processing and select specific frame index -func (av *AVContext) SelectFrame(n int) (err error) { - nn := C.int(n - 1) - if av.thumbContext != nil && nn > av.availableIndex { - nn = av.availableIndex - } - av.selectedIndex = nn - return av.ProcessFrames(-1) -} - -func (av *AVContext) positionToDuration(f float64) time.Duration { - return time.Duration(float64(av.duration) * math.Max(math.Min(f, 1), 0)) -} - -func (av *AVContext) SelectPosition(f float64) (err error) { - return av.SelectDuration(av.positionToDuration(f)) -} - -// SelectDuration seeks to keyframe before the specified duration -// then process frames to find precise duration -func (av *AVContext) SelectDuration(ts time.Duration) (err error) { - if ts > 0 { - av.selectedDuration = ts - if err = av.SeekDuration(ts); err != nil { - return - } - return av.ProcessFrames(-1) - } else { - return av.SelectFrame(1) - } -} - -// SeekPosition seeks to keyframe before specified position percentage between 0 and 1 -// then process frames to find precise position -func (av *AVContext) SeekPosition(f float64) error { - return av.SeekDuration(av.positionToDuration(f)) -} - -// SeekDuration seeks to keyframe before the specified duration -func (av *AVContext) SeekDuration(ts time.Duration) error { - if av.formatContext == nil || av.codecContext == nil { - return ErrDecoderNotFound - } - return seekDuration(av, ts) -} - -// Export frame to RGB or RGBA buffer -func (av *AVContext) Export(bands int) (buf []byte, err error) { - if err = av.ProcessFrames(-1); err != nil { - return - } - if bands < 3 || bands > 4 { - bands = 4 - } - if err = convertFrameToRGB(av, bands); err != nil { - return - } - return exportBuffer(av, bands) -} - -// Close AVContext objects -func (av *AVContext) Close() { - closeAVContext(av) -} - -// Metadata AV metadata -func (av *AVContext) Metadata() *Metadata { - var fps float64 - if av.stream != nil { - fps = float64(av.stream.r_frame_rate.num) / float64(av.stream.r_frame_rate.den) - } - return &Metadata{ - Orientation: av.orientation, - Duration: int(av.duration / time.Millisecond), - Width: av.width, - Height: av.height, - Title: av.title, - Artist: av.artist, - FPS: fps, - HasVideo: av.hasVideo, - HasAudio: av.hasAudio, - } -} - -func closeAVContext(av *AVContext) { - if !av.closed { - if av.frame != nil { - C.av_frame_free(&av.frame) - } - if av.thumbContext != nil { - C.free_thumb_context(av.thumbContext) - } - if av.codecContext != nil { - C.avcodec_free_context(&av.codecContext) - } - if av.formatContext != nil { - C.free_format_context(av.formatContext) - } - pointer.Unref(av.opaque) - av.closed = true - } -} - -func createFormatContext(av *AVContext, callbackFlags C.int) error { - intErr := C.allocate_format_context(&av.formatContext) - if intErr < 0 { - return avError(intErr) - } - av.opaque = pointer.Save(av) - intErr = C.create_format_context(av.formatContext, av.opaque, callbackFlags) - if intErr < 0 { - pointer.Unref(av.opaque) - return avError(intErr) - } - metadata(av) - duration(av) - err := findStreams(av) - if err != nil { - C.free_format_context(av.formatContext) - pointer.Unref(av.opaque) - } - return err -} - -func metadata(av *AVContext) { - var artist, title *C.char - C.get_metadata(av.formatContext, &artist, &title) - av.artist = C.GoString(artist) - av.title = C.GoString(title) -} - -func duration(av *AVContext) { - if av.formatContext.duration > 0 { - av.durationInFormat = true - av.duration = time.Duration(1000 * av.formatContext.duration) - } -} - -func findStreams(av *AVContext) error { - var orientation C.int - err := C.find_streams(av.formatContext, &av.stream, &orientation) - if err < 0 { - return avError(err) - } - av.hasVideo = err&hasVideo != 0 - av.hasAudio = err&hasAudio != 0 - if av.hasVideo { - av.width = int(av.stream.codecpar.width) - av.height = int(av.stream.codecpar.height) - av.orientation = int(orientation) - } - return nil -} - -func createDecoder(av *AVContext) error { - err := C.create_codec_context(av.stream, &av.codecContext) - if err < 0 { - return avError(err) - } - return nil -} - -func seekDuration(av *AVContext, ts time.Duration) error { - tts := C.int64_t(ts.Milliseconds()) * C.AV_TIME_BASE / 1000 - err := C.av_seek_frame(av.formatContext, C.int(-1), tts, C.AVSEEK_FLAG_BACKWARD) - C.avcodec_flush_buffers(av.codecContext) - if err < 0 { - return avError(err) - } - return nil -} - -func incrementDuration(av *AVContext, frame *C.AVFrame, i C.int) { - av.availableIndex = i - if frame.pts != C.AV_NOPTS_VALUE { - ptsToNano := C.int64_t(1000000000 * av.stream.time_base.num / av.stream.time_base.den) - newDuration := time.Duration(frame.pts * ptsToNano) - av.availableDuration = newDuration - - if !av.durationInFormat && newDuration > av.duration { - av.duration = newDuration - } - } -} - -func populateFrames(av *AVContext, frames <-chan *C.AVFrame) <-chan struct{} { - done := make(chan struct{}) - var isSelected = av.selectedIndex > -1 - go func() { - var n C.int - if !isSelected { - for frame := range frames { - C.populate_histogram(av.thumbContext, n, frame) - n++ - } - } else { - for frame := range frames { - C.populate_frame(av.thumbContext, n, frame) - n++ - } - } - av.thumbContext.n = n - close(done) - }() - return done -} - -func createThumbContext(av *AVContext, maxFrames C.int) error { - pkt := C.create_packet() - var frame *C.AVFrame - err := C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame) - if err >= 0 { - incrementDuration(av, frame, 0) - av.thumbContext = C.create_thumb_context(av.stream, frame) - if av.thumbContext == nil { - err = C.int(ErrNoMem) - } - } - if err < 0 { - if pkt.buf != nil { - C.av_packet_unref(&pkt) - } - if frame != nil { - C.av_frame_free(&frame) - } - return avError(err) - } - n := av.thumbContext.max_frames - if maxFrames > 0 && n > maxFrames { - n = maxFrames - } - if av.selectedIndex > -1 && n > av.selectedIndex+1 { - n = av.selectedIndex + 1 - } - if av.selectedDuration > 0 && av.selectedIndex < 0 { - av.selectedIndex = 0 - } - frames := make(chan *C.AVFrame, n) - done := populateFrames(av, frames) - frames <- frame - if pkt.buf != nil { - C.av_packet_unref(&pkt) - } - return populateThumbContext(av, frames, n, done) -} - -func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <-chan struct{}) error { - pkt := C.create_packet() - var frame *C.AVFrame - var err C.int - for i := C.int(1); i < n; i++ { - err = C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame) - if err < 0 { - break - } - incrementDuration(av, frame, i) - frames <- frame - frame = nil - if av.selectedDuration > 0 { - if av.availableDuration <= av.selectedDuration { - av.selectedIndex = i - } else { - break - } - } - } - if av.selectedIndex > av.availableIndex { - av.selectedIndex = av.availableIndex - } - close(frames) - if pkt.buf != nil { - C.av_packet_unref(&pkt) - } - if frame != nil { - C.av_frame_free(&frame) - } - <-done - if err != 0 && err != C.int(ErrEOF) { - return avError(err) - } - if av.selectedIndex < 0 { - av.selectedIndex = C.find_best_frame_index(av.thumbContext) - } - return nil -} - -func convertFrameToRGB(av *AVContext, bands int) error { - var alpha int - if bands == 4 { - alpha = 1 - } - av.frame = C.convert_frame_to_rgb( - C.select_frame(av.thumbContext, av.selectedIndex), C.int(alpha)) - if av.frame == nil { - return ErrNoMem - } - return nil -} - -func exportBuffer(av *AVContext, bands int) ([]byte, error) { - if av.frame == nil { - return nil, ErrInvalidData - } - size := av.height * av.width * bands - buf := C.GoBytes(unsafe.Pointer(av.frame.data[0]), C.int(size)) - return buf, nil -} diff --git a/ffmpeg/ffmpeg.h b/ffmpeg/ffmpeg.h deleted file mode 100644 index 180fbd5..0000000 --- a/ffmpeg/ffmpeg.h +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BUFFER_SIZE 1 << 12 -#define READ_PACKET_FLAG 1 -#define SEEK_PACKET_FLAG 2 -#define HAS_VIDEO_STREAM 1 -#define HAS_AUDIO_STREAM 2 -#define ERR_TOO_BIG FFERRTAG('H','M','M','M') - -struct thumb_frame { - AVFrame *frame; - int *hist; -}; - -typedef struct ThumbContext { - int n, max_frames; - struct thumb_frame *frames; - double *median; - const AVPixFmtDescriptor *desc; - size_t hist_size; -} ThumbContext; - -int allocate_format_context(AVFormatContext **fmt_ctx); - -int create_format_context(AVFormatContext *fmt_ctx, void* opaque, int callbacks); - -void free_format_context(AVFormatContext *fmt_ctx); - -void get_metadata(AVFormatContext *fmt_ctx, char **artist, char **title); - -int find_streams(AVFormatContext *fmt_ctx, AVStream **video_stream, int *orientation); - -int create_codec_context(AVStream *video_stream, AVCodecContext **dec_ctx); - -AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha); - -AVPacket create_packet(); - -int -obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame); - -ThumbContext *create_thumb_context(AVStream *stream, AVFrame *frame); - -void free_thumb_context(ThumbContext *thumb_ctx); - -int find_best_frame_index(ThumbContext *thumb_ctx); - -AVFrame *select_frame(ThumbContext *thumb_ctx, int i); - -void populate_frame(ThumbContext *thumb_ctx, int n, AVFrame *frame); - -void populate_histogram(ThumbContext *thumb_ctx, int n, AVFrame *frame); - -extern int goPacketRead(void *opaque, uint8_t *buf, int buf_size); - -extern int64_t goPacketSeek(void *opaque, int64_t seek, int whence); diff --git a/ffmpeg/ffmpeg_test.go b/ffmpeg/ffmpeg_test.go deleted file mode 100644 index 9364107..0000000 --- a/ffmpeg/ffmpeg_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package ffmpeg - -import ( - "encoding/json" - "fmt" - "github.com/cshum/imagor/vips" - "github.com/cshum/imagor/vips/pointer" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - "io" - "os" - "reflect" - "strings" - "testing" - "time" -) - -var files = []string{ - "everybody-betray-me.mkv", - "alpha-webm.webm", - "schizo.flv", - "macabre.mp4", - "schizo_0.mp4", - "schizo_90.mp4", - "schizo_180.mp4", - "schizo_270.mp4", - "with_cover.mp3", -} - -var noVideo = []string{ - "no_cover.mp3", -} - -var baseDir = "../testdata/" - -func TestAVContext(t *testing.T) { - vips.Startup(nil) - SetFFmpegLogLevel(AVLogDebug) - logger := zap.NewExample() - SetLogging(nil) - log(AVLogDebug, "nop logging") - SetLogging(func(level AVLogLevel, message string) { - message = strings.TrimSuffix(message, "\n") - switch level { - case AVLogTrace, AVLogDebug, AVLogVerbose: - logger.Debug("ffmpeg", zap.String("log", message)) - case AVLogInfo: - logger.Info("ffmpeg", zap.String("log", message)) - case AVLogWarning, AVLogError, AVLogFatal, AVLogPanic: - logger.Warn("ffmpeg", zap.String("log", message)) - } - }) - require.NoError(t, os.MkdirAll(baseDir+"golden/meta", 0755)) - require.NoError(t, os.MkdirAll(baseDir+"golden/export", 0755)) - t.Parallel() - for _, filename := range files { - for _, n := range []int{-1, 1, 5, 10, 9999, 99999} { - name := filename - if n > -1 { - name = fmt.Sprintf("%s-%d", filename, n) - } - t.Run(name, func(t *testing.T) { - path := baseDir + filename - reader, err := os.Open(path) - require.NoError(t, err) - stats, err := os.Stat(path) - require.NoError(t, err) - av, err := LoadAVContext(reader, stats.Size()) - meta := av.Metadata() - metaBuf, err := json.Marshal(meta) - require.NoError(t, err) - goldenFile := baseDir + "golden/meta/" + name + ".meta.json" - if curr, err := os.ReadFile(goldenFile); err == nil { - assert.Equal(t, string(curr), string(metaBuf)) - } else { - require.NoError(t, os.WriteFile(goldenFile, metaBuf, 0666)) - } - require.NoError(t, err) - defer av.Close() - if n == 10 { - require.NoError(t, av.ProcessFrames(n)) - } else if n == 99999 { - require.NoError(t, av.SelectDuration(time.Second)) - } else if n == 9999 { - require.NoError(t, av.SelectPosition(0.7)) - } else if n == 1 { - require.NoError(t, av.SelectDuration(0)) - } else if n == 5 { - require.NoError(t, av.SelectFrame(n)) - } else { - require.NoError(t, av.SeekPosition(0.7)) - } - bands := 4 - if n == 99999 { - bands = 999 - } - buf, err := av.Export(bands) - require.NoError(t, err) - if bands > 4 { - bands = 4 - } - img, err := vips.LoadImageFromMemory(buf, meta.Width, meta.Height, bands) - require.NoError(t, err) - buf, err = img.ExportJpeg(nil) - require.NoError(t, err) - goldenFile = baseDir + "golden/export/" + name + ".jpg" - if curr, err := os.ReadFile(goldenFile); err == nil { - assert.True(t, reflect.DeepEqual(curr, buf)) - } else { - require.NoError(t, os.WriteFile(goldenFile, buf, 0666)) - } - }) - } - } -} - -func TestNoVideo(t *testing.T) { - require.NoError(t, os.MkdirAll(baseDir+"golden/meta", 0755)) - require.NoError(t, os.MkdirAll(baseDir+"golden/export", 0755)) - for _, filename := range noVideo { - for i := 0; i < 2; i++ { - t.Run(fmt.Sprintf("%s-%d", filename, i), func(t *testing.T) { - path := baseDir + filename - reader, err := os.Open(path) - require.NoError(t, err) - stats, err := os.Stat(path) - require.NoError(t, err) - av, err := LoadAVContext(reader, stats.Size()) - require.NoError(t, err) - defer av.Close() - require.Equal(t, ErrDecoderNotFound, av.ProcessFrames(-1)) - meta := av.Metadata() - metaBuf, err := json.Marshal(meta) - require.NoError(t, err) - goldenFile := baseDir + "golden/meta/" + filename + ".meta.json" - if curr, err := os.ReadFile(goldenFile); err == nil { - assert.Equal(t, string(curr), string(metaBuf)) - } else { - require.NoError(t, os.WriteFile(goldenFile, metaBuf, 0666)) - } - if i == 0 { - buf, err := av.Export(3) - require.Empty(t, buf) - assert.Equal(t, ErrDecoderNotFound, err) - } else { - assert.Equal(t, ErrDecoderNotFound, av.SelectFrame(1)) - } - }) - } - } -} - -func TestCorrupted(t *testing.T) { - filename := "macabre.mp4" - path := baseDir + filename - file, err := os.Open(path) - require.NoError(t, err) - reader := &readCloser{ - Reader: io.LimitReader(file, 1024), - Closer: file, - } - stats, err := os.Stat(path) - require.NoError(t, err) - av, err := LoadAVContext(reader, stats.Size()) - require.Equal(t, ErrInvalidData, err) - require.Empty(t, av) -} - -func TestCorruptedOpaque(t *testing.T) { - filename := "macabre.mp4" - path := baseDir + filename - reader, err := os.Open(path) - require.NoError(t, err) - stats, err := os.Stat(path) - require.NoError(t, err) - av, err := LoadAVContext(reader, stats.Size()) - require.NoError(t, err) - defer av.Close() - pointer.Unref(av.opaque) - err = av.ProcessFrames(-1) - assert.Equal(t, ErrUnknown, err) -} - -type readCloser struct { - io.Reader - io.Closer -} diff --git a/ffmpeg/logging.c b/ffmpeg/logging.c deleted file mode 100644 index 45865e8..0000000 --- a/ffmpeg/logging.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "logging.h" - -void goavLogCallback(void *class_ptr, int level, const char *fmt, va_list vl) { - char line[LINE_SZ]; - int print_prefix = 1; - av_log_format_line(class_ptr, level, fmt, vl, line, LINE_SZ, &print_prefix); - goAVLoggingHandler(level, line); -} - -void goavLogSetup() { - av_log_set_callback(goavLogCallback); -} diff --git a/ffmpeg/logging.go b/ffmpeg/logging.go deleted file mode 100644 index 2ac0528..0000000 --- a/ffmpeg/logging.go +++ /dev/null @@ -1,55 +0,0 @@ -package ffmpeg - -// #include "ffmpeg.h" -// #include "logging.h" -import "C" -import "sync" - -// AVLogLevel defines the ffmpeg threshold for dumping information to stderr. -type AVLogLevel int - -// AVLogLevel enum -const ( - AVLogQuiet AVLogLevel = (iota - 1) * 8 - AVLogPanic - AVLogFatal - AVLogError - AVLogWarning - AVLogInfo - AVLogVerbose - AVLogDebug - AVLogTrace -) - -var ( - currentLoggingHandlerFunction = noopLoggingHandler - currentLoggingVerbosity AVLogLevel - onceLogging sync.Once -) - -// SetFFmpegLogLevel allows you to change the log level from the default (AVLogInfo). -func SetFFmpegLogLevel(logLevel AVLogLevel) { - C.av_log_set_level(C.int(logLevel)) - currentLoggingVerbosity = logLevel -} - -type LoggingHandlerFunction func(messageLevel AVLogLevel, message string) - -// SetLogging set AV logging handler -func SetLogging(handler LoggingHandlerFunction) { - onceLogging.Do(func() { - C.goavLogSetup() - }) - if handler != nil { - currentLoggingHandlerFunction = handler - } -} - -func noopLoggingHandler(_ AVLogLevel, _ string) { -} - -func log(level AVLogLevel, message string) { - if level <= currentLoggingVerbosity { - currentLoggingHandlerFunction(level, message) - } -} diff --git a/ffmpeg/logging.h b/ffmpeg/logging.h deleted file mode 100644 index ec6d4c9..0000000 --- a/ffmpeg/logging.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#define LINE_SZ 1024 - -extern void goAVLoggingHandler(int level, char *str); -extern void av_log_set_callback(void (*callback)(void *, int, const char *, va_list)); -extern void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, char *line, int line_size, int *print_prefix); - -void goavLogCallback(void *class_ptr, int level, const char *fmt, va_list vl); - -void goavLogSetup(); diff --git a/go.mod b/go.mod index 300563e..04286d3 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/cshum/imagorvideo +module git.cef.icu/CEF/imagorextended go 1.21 @@ -6,6 +6,7 @@ toolchain go1.21.1 require ( github.com/cshum/imagor v1.4.13 + github.com/cshum/imagorvideo v0.4.13 github.com/gabriel-vasile/mimetype v1.4.4 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 @@ -18,6 +19,8 @@ require ( cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.11 // indirect cloud.google.com/go/storage v1.43.0 // indirect + github.com/antchfx/htmlquery v1.3.2 // indirect + github.com/antchfx/xpath v1.3.1 // indirect github.com/aws/aws-sdk-go v1.54.20 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index 81b39a4..9fed035 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,10 @@ cloud.google.com/go/pubsub v1.40.0/go.mod h1:BVJI4sI2FyXp36KFKvFwcfDRDfR8MiLT8mM cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antchfx/htmlquery v1.3.2 h1:85YdttVkR1rAY+Oiv/nKI4FCimID+NXhDn82kz3mEvs= +github.com/antchfx/htmlquery v1.3.2/go.mod h1:1mbkcEgEarAokJiWhTfr4hR06w/q2ZZjnYLrDt6CTUk= +github.com/antchfx/xpath v1.3.1 h1:PNbFuUqHwWl0xRjvUPjJ95Agbmdj2uzzIwmQKgu4oCk= +github.com/antchfx/xpath v1.3.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/aws/aws-sdk-go v1.54.20 h1:FZ2UcXya7bUkvkpf7TaPmiL7EubK0go1nlXGLRwEsoo= github.com/aws/aws-sdk-go v1.54.20/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -27,6 +31,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cshum/imagor v1.4.13 h1:BFcSpsTUOJj+Wv5SzDeXa8bhsT/Ehw7EcrFD0UTdpmU= github.com/cshum/imagor v1.4.13/go.mod h1:LHxXgks6Y06GzEHitnlO8vcD5gznxIHWPdvGsnlGpMo= +github.com/cshum/imagorvideo v0.4.13 h1:tn+TmdPMvS00XndPX8j/BUMyebErkxXgpJ9CLxNvROE= +github.com/cshum/imagorvideo v0.4.13/go.mod h1:y2g2GQst6b1X+jvAcxhDusTcYYGJqp+fSRcUo3l+PxU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -129,6 +135,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= @@ -151,6 +158,7 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -159,12 +167,17 @@ golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -173,16 +186,27 @@ golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbht golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -192,8 +216,11 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= diff --git a/option.go b/option.go index 50835b2..213a1bd 100644 --- a/option.go +++ b/option.go @@ -1,4 +1,4 @@ -package imagorvideo +package imagorvideoextended import "go.uber.org/zap" diff --git a/processor.go b/processor.go index 4741dbe..bf6fe93 100644 --- a/processor.go +++ b/processor.go @@ -1,16 +1,14 @@ -package imagorvideo +package imagorvideoextended import ( "context" + "github.com/antchfx/htmlquery" "github.com/cshum/imagor" "github.com/cshum/imagor/imagorpath" - "github.com/cshum/imagorvideo/ffmpeg" "github.com/gabriel-vasile/mimetype" "go.uber.org/zap" "io" - "strconv" "strings" - "time" ) // Processor for imagorvideo that implements imagor.Processor interface @@ -33,22 +31,6 @@ func NewProcessor(options ...Option) *Processor { // Startup implements imagor.Processor interface func (p *Processor) Startup(_ context.Context) error { - ffmpeg.SetLogging(func(level ffmpeg.AVLogLevel, message string) { - message = strings.TrimSuffix(message, "\n") - switch level { - case ffmpeg.AVLogTrace, ffmpeg.AVLogDebug, ffmpeg.AVLogVerbose: - p.Logger.Debug("ffmpeg", zap.String("log", message)) - case ffmpeg.AVLogInfo: - p.Logger.Info("ffmpeg", zap.String("log", message)) - case ffmpeg.AVLogWarning, ffmpeg.AVLogError, ffmpeg.AVLogFatal, ffmpeg.AVLogPanic: - p.Logger.Warn("ffmpeg", zap.String("log", message)) - } - }) - if p.Debug { - ffmpeg.SetFFmpegLogLevel(ffmpeg.AVLogDebug) - } else { - ffmpeg.SetFFmpegLogLevel(ffmpeg.AVLogError) - } return nil } @@ -75,15 +57,15 @@ func (p *Processor) Process(ctx context.Context, in *imagor.Blob, params imagorp } } }() - var filters imagorpath.Filters var mime = mimetype.Detect(in.Sniff()) - if typ := mime.String(); !strings.HasPrefix(typ, "video/") && - !strings.HasPrefix(typ, "audio/") { + + if typ := mime.String(); !strings.HasPrefix(typ, "text/html") { // forward identical for non video nor audio err = imagor.ErrForward{Params: params} out = in return } + rs, size, err := in.NewReadSeeker() if err != nil { return @@ -100,95 +82,61 @@ func (p *Processor) Process(ctx context.Context, in *imagor.Blob, params imagorp return } } - av, err := ffmpeg.LoadAVContext(rs, size) + all, err := in.ReadAll() if err != nil { - return + return nil, err } - defer av.Close() - meta := av.Metadata() - if params.Meta { - out = imagor.NewBlobFromJsonMarshal(Metadata{ - Format: strings.TrimPrefix(mime.Extension(), "."), - ContentType: mime.String(), - Metadata: meta, - }) - return + + doc, err := htmlquery.Parse(strings.NewReader(string(all[:]))) + meta := Metadata{ + Format: strings.TrimPrefix(mime.Extension(), "."), + Title: "", + Description: "", + Image: "", } - bands := 3 - for _, filter := range params.Filters { - switch filter.Name { - case "format": - switch strings.ToLower(filter.Args) { - case "webp", "png", "gif": - switch mime.Extension() { - case ".webm", ".flv", ".mov", ".avi": - bands = 4 - } - } - case "frame": - if ts, e := time.ParseDuration(filter.Args); e == nil { - if err = av.SelectDuration(ts); err != nil { - return - } - } else if f, e := strconv.ParseFloat(filter.Args, 64); e == nil { - if strings.Contains(filter.Args, ".") { - if err = av.SelectPosition(f); err != nil { - return - } - } else if n := int(f); n >= 1 { - if err = av.SelectFrame(n); err != nil { - return - } - } - } - case "seek": - if ts, e := time.ParseDuration(filter.Args); e == nil { - if err = av.SeekDuration(ts); err != nil { - return - } - } else if f, e := strconv.ParseFloat(filter.Args, 64); e == nil { - if err = av.SeekPosition(f); err != nil { - return - } - } - case "max_frames": - n, _ := strconv.Atoi(filter.Args) - if err = av.ProcessFrames(n); err != nil { - return - } + metaTags := htmlquery.Find(doc, "//meta[@property]") + for _, metaTag := range metaTags { + var property = htmlquery.SelectAttr(metaTag, "property") + var val = htmlquery.SelectAttr(metaTag, "content") + + switch property { + case "og:image": + fallthrough + case "twitter:image:src": + meta.Image = val + break + + case "og:title": + fallthrough + case "twitter:title": + meta.Title = val + break + + case "twitter:description": + fallthrough + case "og:description": + meta.Description = val + } + } + if meta.Title == "" { + title := htmlquery.FindOne(doc, "//title") + if title != nil { + meta.Title = htmlquery.InnerText(title) + } else { + meta.Title = in.FilePath() } } - switch meta.Orientation { - case 3: - filters = append(filters, imagorpath.Filter{Name: "orient", Args: "180"}) - case 6: - filters = append(filters, imagorpath.Filter{Name: "orient", Args: "270"}) - case 8: - filters = append(filters, imagorpath.Filter{Name: "orient", Args: "90"}) - } - buf, err := av.Export(bands) - if err != nil || len(buf) == 0 { - if err == nil { - err = imagor.ErrUnsupportedFormat - } - return - } - out = imagor.NewBlobFromMemory(buf, meta.Width, meta.Height, bands) - - if len(filters) > 0 { - params.Filters = append(params.Filters, filters...) - params.Path = imagorpath.GeneratePath(params) - } - err = imagor.ErrForward{Params: params} + out = imagor.NewBlobFromJsonMarshal(meta) return } // Metadata imagorvideo metadata type Metadata struct { Format string `json:"format"` - ContentType string `json:"content_type"` - *ffmpeg.Metadata + Title string `json:"title"` + Description string `json:"description"` + Image string `json:"image"` } var transPixel = []byte("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x21\xF9\x04\x01\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B") diff --git a/processor_test.go b/processor_test.go index 5fd9e23..c3fc0b0 100644 --- a/processor_test.go +++ b/processor_test.go @@ -1,4 +1,4 @@ -package imagorvideo +package imagorvideoextended import ( "context" diff --git a/testdata/alpha-webm.webm b/testdata/alpha-webm.webm deleted file mode 100644 index add19f2..0000000 Binary files a/testdata/alpha-webm.webm and /dev/null differ diff --git a/testdata/black.jpg b/testdata/black.jpg deleted file mode 100644 index 3bc9832..0000000 Binary files a/testdata/black.jpg and /dev/null differ diff --git a/testdata/demo.jpg b/testdata/demo.jpg deleted file mode 100644 index 9340745..0000000 Binary files a/testdata/demo.jpg and /dev/null differ diff --git a/testdata/demo.png b/testdata/demo.png deleted file mode 100644 index 24b35b4..0000000 Binary files a/testdata/demo.png and /dev/null differ diff --git a/testdata/demo2.jpg b/testdata/demo2.jpg deleted file mode 100644 index 247add8..0000000 Binary files a/testdata/demo2.jpg and /dev/null differ diff --git a/testdata/demo3.jpg b/testdata/demo3.jpg deleted file mode 100644 index 0f31c87..0000000 Binary files a/testdata/demo3.jpg and /dev/null differ diff --git a/testdata/everybody-betray-me.mkv b/testdata/everybody-betray-me.mkv deleted file mode 100644 index 3e58df8..0000000 Binary files a/testdata/everybody-betray-me.mkv and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm-1.jpg b/testdata/golden/export/alpha-webm.webm-1.jpg deleted file mode 100644 index a826544..0000000 Binary files a/testdata/golden/export/alpha-webm.webm-1.jpg and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm-10.jpg b/testdata/golden/export/alpha-webm.webm-10.jpg deleted file mode 100644 index 620e1b2..0000000 Binary files a/testdata/golden/export/alpha-webm.webm-10.jpg and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm-5.jpg b/testdata/golden/export/alpha-webm.webm-5.jpg deleted file mode 100644 index 620e1b2..0000000 Binary files a/testdata/golden/export/alpha-webm.webm-5.jpg and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm-9999.jpg b/testdata/golden/export/alpha-webm.webm-9999.jpg deleted file mode 100644 index c97a86f..0000000 Binary files a/testdata/golden/export/alpha-webm.webm-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm-99999.jpg b/testdata/golden/export/alpha-webm.webm-99999.jpg deleted file mode 100644 index 3b035d3..0000000 Binary files a/testdata/golden/export/alpha-webm.webm-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/alpha-webm.webm.jpg b/testdata/golden/export/alpha-webm.webm.jpg deleted file mode 100644 index 3312405..0000000 Binary files a/testdata/golden/export/alpha-webm.webm.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv-1.jpg b/testdata/golden/export/everybody-betray-me.mkv-1.jpg deleted file mode 100644 index 6ad3311..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv-1.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv-10.jpg b/testdata/golden/export/everybody-betray-me.mkv-10.jpg deleted file mode 100644 index 62127fd..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv-10.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv-5.jpg b/testdata/golden/export/everybody-betray-me.mkv-5.jpg deleted file mode 100644 index b14e987..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv-5.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv-9999.jpg b/testdata/golden/export/everybody-betray-me.mkv-9999.jpg deleted file mode 100644 index 45a2a70..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv-99999.jpg b/testdata/golden/export/everybody-betray-me.mkv-99999.jpg deleted file mode 100644 index cfd2ad9..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/everybody-betray-me.mkv.jpg b/testdata/golden/export/everybody-betray-me.mkv.jpg deleted file mode 100644 index 5c2f430..0000000 Binary files a/testdata/golden/export/everybody-betray-me.mkv.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4-1.jpg b/testdata/golden/export/macabre.mp4-1.jpg deleted file mode 100644 index d1ab9d8..0000000 Binary files a/testdata/golden/export/macabre.mp4-1.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4-10.jpg b/testdata/golden/export/macabre.mp4-10.jpg deleted file mode 100644 index dbe27e7..0000000 Binary files a/testdata/golden/export/macabre.mp4-10.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4-5.jpg b/testdata/golden/export/macabre.mp4-5.jpg deleted file mode 100644 index dbe27e7..0000000 Binary files a/testdata/golden/export/macabre.mp4-5.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4-9999.jpg b/testdata/golden/export/macabre.mp4-9999.jpg deleted file mode 100644 index 59f5451..0000000 Binary files a/testdata/golden/export/macabre.mp4-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4-99999.jpg b/testdata/golden/export/macabre.mp4-99999.jpg deleted file mode 100644 index 59f5451..0000000 Binary files a/testdata/golden/export/macabre.mp4-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/macabre.mp4.jpg b/testdata/golden/export/macabre.mp4.jpg deleted file mode 100644 index 4b4a16d..0000000 Binary files a/testdata/golden/export/macabre.mp4.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv-1.jpg b/testdata/golden/export/schizo.flv-1.jpg deleted file mode 100644 index a543ab0..0000000 Binary files a/testdata/golden/export/schizo.flv-1.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv-10.jpg b/testdata/golden/export/schizo.flv-10.jpg deleted file mode 100644 index fb1d4da..0000000 Binary files a/testdata/golden/export/schizo.flv-10.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv-5.jpg b/testdata/golden/export/schizo.flv-5.jpg deleted file mode 100644 index 0cd4f61..0000000 Binary files a/testdata/golden/export/schizo.flv-5.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv-9999.jpg b/testdata/golden/export/schizo.flv-9999.jpg deleted file mode 100644 index 5d21aa1..0000000 Binary files a/testdata/golden/export/schizo.flv-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv-99999.jpg b/testdata/golden/export/schizo.flv-99999.jpg deleted file mode 100644 index a86490f..0000000 Binary files a/testdata/golden/export/schizo.flv-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo.flv.jpg b/testdata/golden/export/schizo.flv.jpg deleted file mode 100644 index 895b026..0000000 Binary files a/testdata/golden/export/schizo.flv.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4-1.jpg b/testdata/golden/export/schizo_0.mp4-1.jpg deleted file mode 100644 index 9d49888..0000000 Binary files a/testdata/golden/export/schizo_0.mp4-1.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4-10.jpg b/testdata/golden/export/schizo_0.mp4-10.jpg deleted file mode 100644 index fcccf00..0000000 Binary files a/testdata/golden/export/schizo_0.mp4-10.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4-5.jpg b/testdata/golden/export/schizo_0.mp4-5.jpg deleted file mode 100644 index 7c9e9a8..0000000 Binary files a/testdata/golden/export/schizo_0.mp4-5.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4-9999.jpg b/testdata/golden/export/schizo_0.mp4-9999.jpg deleted file mode 100644 index 935ab8e..0000000 Binary files a/testdata/golden/export/schizo_0.mp4-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4-99999.jpg b/testdata/golden/export/schizo_0.mp4-99999.jpg deleted file mode 100644 index 935ab8e..0000000 Binary files a/testdata/golden/export/schizo_0.mp4-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_0.mp4.jpg b/testdata/golden/export/schizo_0.mp4.jpg deleted file mode 100644 index bde6e23..0000000 Binary files a/testdata/golden/export/schizo_0.mp4.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4-1.jpg b/testdata/golden/export/schizo_180.mp4-1.jpg deleted file mode 100644 index df99457..0000000 Binary files a/testdata/golden/export/schizo_180.mp4-1.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4-10.jpg b/testdata/golden/export/schizo_180.mp4-10.jpg deleted file mode 100644 index fe011e5..0000000 Binary files a/testdata/golden/export/schizo_180.mp4-10.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4-5.jpg b/testdata/golden/export/schizo_180.mp4-5.jpg deleted file mode 100644 index fe011e5..0000000 Binary files a/testdata/golden/export/schizo_180.mp4-5.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4-9999.jpg b/testdata/golden/export/schizo_180.mp4-9999.jpg deleted file mode 100644 index 15f6245..0000000 Binary files a/testdata/golden/export/schizo_180.mp4-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4-99999.jpg b/testdata/golden/export/schizo_180.mp4-99999.jpg deleted file mode 100644 index 15f6245..0000000 Binary files a/testdata/golden/export/schizo_180.mp4-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_180.mp4.jpg b/testdata/golden/export/schizo_180.mp4.jpg deleted file mode 100644 index de2ac07..0000000 Binary files a/testdata/golden/export/schizo_180.mp4.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4-1.jpg b/testdata/golden/export/schizo_270.mp4-1.jpg deleted file mode 100644 index 8f2ada3..0000000 Binary files a/testdata/golden/export/schizo_270.mp4-1.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4-10.jpg b/testdata/golden/export/schizo_270.mp4-10.jpg deleted file mode 100644 index 996cc9e..0000000 Binary files a/testdata/golden/export/schizo_270.mp4-10.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4-5.jpg b/testdata/golden/export/schizo_270.mp4-5.jpg deleted file mode 100644 index e2827e9..0000000 Binary files a/testdata/golden/export/schizo_270.mp4-5.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4-9999.jpg b/testdata/golden/export/schizo_270.mp4-9999.jpg deleted file mode 100644 index b367d33..0000000 Binary files a/testdata/golden/export/schizo_270.mp4-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4-99999.jpg b/testdata/golden/export/schizo_270.mp4-99999.jpg deleted file mode 100644 index b367d33..0000000 Binary files a/testdata/golden/export/schizo_270.mp4-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_270.mp4.jpg b/testdata/golden/export/schizo_270.mp4.jpg deleted file mode 100644 index 8ac4052..0000000 Binary files a/testdata/golden/export/schizo_270.mp4.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4-1.jpg b/testdata/golden/export/schizo_90.mp4-1.jpg deleted file mode 100644 index 3ef8b0c..0000000 Binary files a/testdata/golden/export/schizo_90.mp4-1.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4-10.jpg b/testdata/golden/export/schizo_90.mp4-10.jpg deleted file mode 100644 index 6e8c781..0000000 Binary files a/testdata/golden/export/schizo_90.mp4-10.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4-5.jpg b/testdata/golden/export/schizo_90.mp4-5.jpg deleted file mode 100644 index 13ddd38..0000000 Binary files a/testdata/golden/export/schizo_90.mp4-5.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4-9999.jpg b/testdata/golden/export/schizo_90.mp4-9999.jpg deleted file mode 100644 index e57f442..0000000 Binary files a/testdata/golden/export/schizo_90.mp4-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4-99999.jpg b/testdata/golden/export/schizo_90.mp4-99999.jpg deleted file mode 100644 index e57f442..0000000 Binary files a/testdata/golden/export/schizo_90.mp4-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/schizo_90.mp4.jpg b/testdata/golden/export/schizo_90.mp4.jpg deleted file mode 100644 index 6a96a5f..0000000 Binary files a/testdata/golden/export/schizo_90.mp4.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3-1.jpg b/testdata/golden/export/with_cover.mp3-1.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3-1.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3-10.jpg b/testdata/golden/export/with_cover.mp3-10.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3-10.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3-5.jpg b/testdata/golden/export/with_cover.mp3-5.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3-5.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3-9999.jpg b/testdata/golden/export/with_cover.mp3-9999.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3-9999.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3-99999.jpg b/testdata/golden/export/with_cover.mp3-99999.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3-99999.jpg and /dev/null differ diff --git a/testdata/golden/export/with_cover.mp3.jpg b/testdata/golden/export/with_cover.mp3.jpg deleted file mode 100644 index aac8c5c..0000000 Binary files a/testdata/golden/export/with_cover.mp3.jpg and /dev/null differ diff --git a/testdata/golden/meta/alpha-webm.webm-1.meta.json b/testdata/golden/meta/alpha-webm.webm-1.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/alpha-webm.webm-10.meta.json b/testdata/golden/meta/alpha-webm.webm-10.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/alpha-webm.webm-5.meta.json b/testdata/golden/meta/alpha-webm.webm-5.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/alpha-webm.webm-9999.meta.json b/testdata/golden/meta/alpha-webm.webm-9999.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/alpha-webm.webm-99999.meta.json b/testdata/golden/meta/alpha-webm.webm-99999.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/alpha-webm.webm.meta.json b/testdata/golden/meta/alpha-webm.webm.meta.json deleted file mode 100644 index e45c027..0000000 --- a/testdata/golden/meta/alpha-webm.webm.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":12040,"width":720,"height":576,"fps":25,"has_video":true,"has_audio":false} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv-1.meta.json b/testdata/golden/meta/everybody-betray-me.mkv-1.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv-10.meta.json b/testdata/golden/meta/everybody-betray-me.mkv-10.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv-5.meta.json b/testdata/golden/meta/everybody-betray-me.mkv-5.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv-9999.meta.json b/testdata/golden/meta/everybody-betray-me.mkv-9999.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv-99999.meta.json b/testdata/golden/meta/everybody-betray-me.mkv-99999.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/everybody-betray-me.mkv.meta.json b/testdata/golden/meta/everybody-betray-me.mkv.meta.json deleted file mode 100644 index 1444d9e..0000000 --- a/testdata/golden/meta/everybody-betray-me.mkv.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4-1.meta.json b/testdata/golden/meta/macabre.mp4-1.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4-10.meta.json b/testdata/golden/meta/macabre.mp4-10.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4-5.meta.json b/testdata/golden/meta/macabre.mp4-5.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4-9999.meta.json b/testdata/golden/meta/macabre.mp4-9999.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4-99999.meta.json b/testdata/golden/meta/macabre.mp4-99999.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/macabre.mp4.meta.json b/testdata/golden/meta/macabre.mp4.meta.json deleted file mode 100644 index 67cbce9..0000000 --- a/testdata/golden/meta/macabre.mp4.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/no_cover.mp3.meta.json b/testdata/golden/meta/no_cover.mp3.meta.json deleted file mode 100644 index 8526068..0000000 --- a/testdata/golden/meta/no_cover.mp3.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":0,"duration":13536,"has_video":false,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv-1.meta.json b/testdata/golden/meta/schizo.flv-1.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv-10.meta.json b/testdata/golden/meta/schizo.flv-10.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv-5.meta.json b/testdata/golden/meta/schizo.flv-5.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv-9999.meta.json b/testdata/golden/meta/schizo.flv-9999.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv-99999.meta.json b/testdata/golden/meta/schizo.flv-99999.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo.flv.meta.json b/testdata/golden/meta/schizo.flv.meta.json deleted file mode 100644 index eaa82ba..0000000 --- a/testdata/golden/meta/schizo.flv.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2560,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4-1.meta.json b/testdata/golden/meta/schizo_0.mp4-1.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4-10.meta.json b/testdata/golden/meta/schizo_0.mp4-10.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4-5.meta.json b/testdata/golden/meta/schizo_0.mp4-5.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4-9999.meta.json b/testdata/golden/meta/schizo_0.mp4-9999.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4-99999.meta.json b/testdata/golden/meta/schizo_0.mp4-99999.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_0.mp4.meta.json b/testdata/golden/meta/schizo_0.mp4.meta.json deleted file mode 100644 index d98cf3c..0000000 --- a/testdata/golden/meta/schizo_0.mp4.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4-1.meta.json b/testdata/golden/meta/schizo_180.mp4-1.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4-10.meta.json b/testdata/golden/meta/schizo_180.mp4-10.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4-5.meta.json b/testdata/golden/meta/schizo_180.mp4-5.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4-9999.meta.json b/testdata/golden/meta/schizo_180.mp4-9999.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4-99999.meta.json b/testdata/golden/meta/schizo_180.mp4-99999.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_180.mp4.meta.json b/testdata/golden/meta/schizo_180.mp4.meta.json deleted file mode 100644 index 0dfaf2b..0000000 --- a/testdata/golden/meta/schizo_180.mp4.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4-1.meta.json b/testdata/golden/meta/schizo_270.mp4-1.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4-10.meta.json b/testdata/golden/meta/schizo_270.mp4-10.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4-5.meta.json b/testdata/golden/meta/schizo_270.mp4-5.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4-9999.meta.json b/testdata/golden/meta/schizo_270.mp4-9999.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4-99999.meta.json b/testdata/golden/meta/schizo_270.mp4-99999.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_270.mp4.meta.json b/testdata/golden/meta/schizo_270.mp4.meta.json deleted file mode 100644 index ecdd37c..0000000 --- a/testdata/golden/meta/schizo_270.mp4.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4-1.meta.json b/testdata/golden/meta/schizo_90.mp4-1.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4-10.meta.json b/testdata/golden/meta/schizo_90.mp4-10.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4-5.meta.json b/testdata/golden/meta/schizo_90.mp4-5.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4-9999.meta.json b/testdata/golden/meta/schizo_90.mp4-9999.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4-99999.meta.json b/testdata/golden/meta/schizo_90.mp4-99999.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/schizo_90.mp4.meta.json b/testdata/golden/meta/schizo_90.mp4.meta.json deleted file mode 100644 index 90e1578..0000000 --- a/testdata/golden/meta/schizo_90.mp4.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3-1.meta.json b/testdata/golden/meta/with_cover.mp3-1.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3-1.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3-10.meta.json b/testdata/golden/meta/with_cover.mp3-10.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3-10.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3-5.meta.json b/testdata/golden/meta/with_cover.mp3-5.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3-5.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3-9999.meta.json b/testdata/golden/meta/with_cover.mp3-9999.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3-9999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3-99999.meta.json b/testdata/golden/meta/with_cover.mp3-99999.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3-99999.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/meta/with_cover.mp3.meta.json b/testdata/golden/meta/with_cover.mp3.meta.json deleted file mode 100644 index 00ce5c9..0000000 --- a/testdata/golden/meta/with_cover.mp3.meta.json +++ /dev/null @@ -1 +0,0 @@ -{"orientation":1,"duration":1906,"width":1280,"height":720,"fps":90000,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/result-fallback-image/filters%3Aseek%280.1%29/no_cover.mp3 b/testdata/golden/result-fallback-image/filters%3Aseek%280.1%29/no_cover.mp3 deleted file mode 100644 index 8c74ba6..0000000 --- a/testdata/golden/result-fallback-image/filters%3Aseek%280.1%29/no_cover.mp3 +++ /dev/null @@ -1 +0,0 @@ -{"message":"ffmpeg: decoder not found","status":406} \ No newline at end of file diff --git a/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv b/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv deleted file mode 100644 index 57dc1fc..0000000 --- a/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv +++ /dev/null @@ -1 +0,0 @@ -{"message":"ffmpeg: invalid data found when processing input","status":406} \ No newline at end of file diff --git a/testdata/golden/result/200x100/schizo_0.mp4 b/testdata/golden/result/200x100/schizo_0.mp4 deleted file mode 100644 index b8d3bf5..0000000 Binary files a/testdata/golden/result/200x100/schizo_0.mp4 and /dev/null differ diff --git a/testdata/golden/result/200x100/schizo_180.mp4 b/testdata/golden/result/200x100/schizo_180.mp4 deleted file mode 100644 index 998ebb8..0000000 Binary files a/testdata/golden/result/200x100/schizo_180.mp4 and /dev/null differ diff --git a/testdata/golden/result/200x100/schizo_270.mp4 b/testdata/golden/result/200x100/schizo_270.mp4 deleted file mode 100644 index d171995..0000000 Binary files a/testdata/golden/result/200x100/schizo_270.mp4 and /dev/null differ diff --git a/testdata/golden/result/220x100/schizo_90.mp4 b/testdata/golden/result/220x100/schizo_90.mp4 deleted file mode 100644 index a91abbb..0000000 Binary files a/testdata/golden/result/220x100/schizo_90.mp4 and /dev/null differ diff --git a/testdata/golden/result/500x/filters%3Aframe%280.5%29%3Aformat%28png%29/alpha-webm.webm b/testdata/golden/result/500x/filters%3Aframe%280.5%29%3Aformat%28png%29/alpha-webm.webm deleted file mode 100644 index fd12e7d..0000000 Binary files a/testdata/golden/result/500x/filters%3Aframe%280.5%29%3Aformat%28png%29/alpha-webm.webm and /dev/null differ diff --git a/testdata/golden/result/500x/filters%3Aframe%285s%29%3Aformat%28png%29/alpha-webm.webm b/testdata/golden/result/500x/filters%3Aframe%285s%29%3Aformat%28png%29/alpha-webm.webm deleted file mode 100644 index 974796f..0000000 Binary files a/testdata/golden/result/500x/filters%3Aframe%285s%29%3Aformat%28png%29/alpha-webm.webm and /dev/null differ diff --git a/testdata/golden/result/500x/filters%3Aseek%280.5%29%3Aformat%28png%29/alpha-webm.webm b/testdata/golden/result/500x/filters%3Aseek%280.5%29%3Aformat%28png%29/alpha-webm.webm deleted file mode 100644 index 718e4ae..0000000 Binary files a/testdata/golden/result/500x/filters%3Aseek%280.5%29%3Aformat%28png%29/alpha-webm.webm and /dev/null differ diff --git a/testdata/golden/result/500x/filters%3Aseek%285s%29%3Aformat%28png%29/alpha-webm.webm b/testdata/golden/result/500x/filters%3Aseek%285s%29%3Aformat%28png%29/alpha-webm.webm deleted file mode 100644 index 6e245c3..0000000 Binary files a/testdata/golden/result/500x/filters%3Aseek%285s%29%3Aformat%28png%29/alpha-webm.webm and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv deleted file mode 100644 index 57dc1fc..0000000 --- a/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv +++ /dev/null @@ -1 +0,0 @@ -{"message":"ffmpeg: invalid data found when processing input","status":406} \ No newline at end of file diff --git a/testdata/golden/result/fit-in/100x100/demo.png b/testdata/golden/result/fit-in/100x100/demo.png deleted file mode 100644 index f14be8b..0000000 Binary files a/testdata/golden/result/fit-in/100x100/demo.png and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/everybody-betray-me.mkv deleted file mode 100644 index 22c2fed..0000000 Binary files a/testdata/golden/result/fit-in/100x100/everybody-betray-me.mkv and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/filters%3Aframe%283%29/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/filters%3Aframe%283%29/everybody-betray-me.mkv deleted file mode 100644 index 312b0e1..0000000 Binary files a/testdata/golden/result/fit-in/100x100/filters%3Aframe%283%29/everybody-betray-me.mkv and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/filters%3Aframe%2899999%29/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/filters%3Aframe%2899999%29/everybody-betray-me.mkv deleted file mode 100644 index 666edac..0000000 Binary files a/testdata/golden/result/fit-in/100x100/filters%3Aframe%2899999%29/everybody-betray-me.mkv and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/filters%3Amax_frames%286%29/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/filters%3Amax_frames%286%29/everybody-betray-me.mkv deleted file mode 100644 index 36991fa..0000000 Binary files a/testdata/golden/result/fit-in/100x100/filters%3Amax_frames%286%29/everybody-betray-me.mkv and /dev/null differ diff --git a/testdata/golden/result/fit-in/100x100/no_cover.mp3 b/testdata/golden/result/fit-in/100x100/no_cover.mp3 deleted file mode 100644 index 8c74ba6..0000000 --- a/testdata/golden/result/fit-in/100x100/no_cover.mp3 +++ /dev/null @@ -1 +0,0 @@ -{"message":"ffmpeg: decoder not found","status":406} \ No newline at end of file diff --git a/testdata/golden/result/fit-in/filters%3Aformat%28png%29/alpha-webm.webm b/testdata/golden/result/fit-in/filters%3Aformat%28png%29/alpha-webm.webm deleted file mode 100644 index abc1087..0000000 Binary files a/testdata/golden/result/fit-in/filters%3Aformat%28png%29/alpha-webm.webm and /dev/null differ diff --git a/testdata/golden/result/meta/everybody-betray-me.mkv b/testdata/golden/result/meta/everybody-betray-me.mkv deleted file mode 100644 index 586d7e6..0000000 --- a/testdata/golden/result/meta/everybody-betray-me.mkv +++ /dev/null @@ -1 +0,0 @@ -{"format":"mkv","content_type":"video/x-matroska","orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/result/meta/filters%3Amax_frames%28%29/everybody-betray-me.mkv b/testdata/golden/result/meta/filters%3Amax_frames%28%29/everybody-betray-me.mkv deleted file mode 100644 index 586d7e6..0000000 --- a/testdata/golden/result/meta/filters%3Amax_frames%28%29/everybody-betray-me.mkv +++ /dev/null @@ -1 +0,0 @@ -{"format":"mkv","content_type":"video/x-matroska","orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/result/meta/filters%3Amax_frames%286%29/everybody-betray-me.mkv b/testdata/golden/result/meta/filters%3Amax_frames%286%29/everybody-betray-me.mkv deleted file mode 100644 index 586d7e6..0000000 --- a/testdata/golden/result/meta/filters%3Amax_frames%286%29/everybody-betray-me.mkv +++ /dev/null @@ -1 +0,0 @@ -{"format":"mkv","content_type":"video/x-matroska","orientation":1,"duration":7407,"width":640,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true} \ No newline at end of file diff --git a/testdata/golden/result/meta/no_cover.mp3 b/testdata/golden/result/meta/no_cover.mp3 deleted file mode 100644 index 6f0994b..0000000 --- a/testdata/golden/result/meta/no_cover.mp3 +++ /dev/null @@ -1 +0,0 @@ -{"format":"mp3","content_type":"audio/mpeg","orientation":0,"duration":13536,"has_video":false,"has_audio":true} \ No newline at end of file diff --git a/testdata/macabre.mp4 b/testdata/macabre.mp4 deleted file mode 100644 index 0177b9c..0000000 Binary files a/testdata/macabre.mp4 and /dev/null differ diff --git a/testdata/no_cover.mp3 b/testdata/no_cover.mp3 deleted file mode 100644 index 9c6f3d9..0000000 Binary files a/testdata/no_cover.mp3 and /dev/null differ diff --git a/testdata/schizo.flv b/testdata/schizo.flv deleted file mode 100644 index 2e3efa1..0000000 Binary files a/testdata/schizo.flv and /dev/null differ diff --git a/testdata/schizo_0.mp4 b/testdata/schizo_0.mp4 deleted file mode 100644 index 2047fc8..0000000 Binary files a/testdata/schizo_0.mp4 and /dev/null differ diff --git a/testdata/schizo_180.mp4 b/testdata/schizo_180.mp4 deleted file mode 100644 index 7ae8a74..0000000 Binary files a/testdata/schizo_180.mp4 and /dev/null differ diff --git a/testdata/schizo_270.mp4 b/testdata/schizo_270.mp4 deleted file mode 100644 index 1b6450e..0000000 Binary files a/testdata/schizo_270.mp4 and /dev/null differ diff --git a/testdata/schizo_90.mp4 b/testdata/schizo_90.mp4 deleted file mode 100644 index b110972..0000000 Binary files a/testdata/schizo_90.mp4 and /dev/null differ diff --git a/testdata/seek5m.jpg b/testdata/seek5m.jpg deleted file mode 100644 index d800142..0000000 Binary files a/testdata/seek5m.jpg and /dev/null differ diff --git a/testdata/with_cover.mp3 b/testdata/with_cover.mp3 deleted file mode 100644 index b5995f9..0000000 Binary files a/testdata/with_cover.mp3 and /dev/null differ