stash/pkg/ffmpeg/media_detection.go

67 lines
1.4 KiB
Go

package ffmpeg
import (
"bytes"
"github.com/stashapp/stash/pkg/logger"
"os"
)
// detect file format from magic file number
// https://github.com/lex-r/filetype/blob/73c10ad714e3b8ecf5cd1564c882ed6d440d5c2d/matchers/video.go
func mkv(buf []byte) bool {
return len(buf) > 3 &&
buf[0] == 0x1A && buf[1] == 0x45 &&
buf[2] == 0xDF && buf[3] == 0xA3 &&
containsMatroskaSignature(buf, []byte{'m', 'a', 't', 'r', 'o', 's', 'k', 'a'})
}
func webm(buf []byte) bool {
return len(buf) > 3 &&
buf[0] == 0x1A && buf[1] == 0x45 &&
buf[2] == 0xDF && buf[3] == 0xA3 &&
containsMatroskaSignature(buf, []byte{'w', 'e', 'b', 'm'})
}
func containsMatroskaSignature(buf, subType []byte) bool {
limit := 4096
if len(buf) < limit {
limit = len(buf)
}
index := bytes.Index(buf[:limit], subType)
if index < 3 {
return false
}
return buf[index-3] == 0x42 && buf[index-2] == 0x82
}
//returns container as string ("" on error or no match)
//implements only mkv or webm as ffprobe can't distinguish between them
//and not all browsers support mkv
func MagicContainer(file_path string) Container {
file, err := os.Open(file_path)
if err != nil {
logger.Errorf("[magicfile] %v", err)
return ""
}
defer file.Close()
buf := make([]byte, 4096)
_, err = file.Read(buf)
if err != nil {
logger.Errorf("[magicfile] %v", err)
return ""
}
if webm(buf) {
return Webm
}
if mkv(buf) {
return Matroska
}
return ""
}