WIP
This commit is contained in:
parent
08ba577b27
commit
3ba52e60cf
114
.github/workflows/build-release.yml
vendored
Normal file
114
.github/workflows/build-release.yml
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
name: build release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '[0-9]+.[0-9]+.[0-9]+'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '1.13.0'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make -j $(nproc) compile VERSION=${{ github.ref }}
|
||||||
|
|
||||||
|
- name: create release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@latest
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Release ${{ github.ref }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
|
||||||
|
- name: darwin-386
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-darwin-386
|
||||||
|
asset_name: ${{ github.event.repository.name }}-darwin-386
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: darwin-amd64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-darwin-amd64
|
||||||
|
asset_name: ${{ github.event.repository.name }}-darwin-amd64
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: freebsd-386
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-386
|
||||||
|
asset_name: ${{ github.event.repository.name }}-freebsd-386
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: freebsd-amd64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-amd64
|
||||||
|
asset_name: ${{ github.event.repository.name }}-freebsd-amd64
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: linux-386
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-linux-386
|
||||||
|
asset_name: ${{ github.event.repository.name }}-linux-386
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: linux-amd64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-linux-amd64
|
||||||
|
asset_name: ${{ github.event.repository.name }}-linux-amd64
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: windows-386
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-windows-386.exe
|
||||||
|
asset_name: ${{ github.event.repository.name }}-windows-386.exe
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
- name: windows-amd64
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./bin/${{ github.event.repository.name }}-windows-amd64.exe
|
||||||
|
asset_name: ${{ github.event.repository.name }}-windows-amd64.exe
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
21
Makefile
21
Makefile
@ -1,16 +1,19 @@
|
|||||||
NAME=range-gen
|
NAME = range-gen
|
||||||
VERSION=0.1.0
|
VERSION = dev_$(shell date +%F_%T)
|
||||||
GOCMD=go
|
GOCMD = go
|
||||||
LDFLAGS:="$(LDFLAGS) -X 'main.Version=$(VERSION)'"
|
LDFLAGS := "$(LDFLAGS) -X 'main.Version=$(VERSION)'"
|
||||||
GOBUILD=$(GOCMD) build -ldflags=$(LDFLAGS)
|
GOBUILD = $(GOCMD) build -ldflags=$(LDFLAGS)
|
||||||
SRCMAIN=.
|
SRCMAIN = .
|
||||||
BINDIR=bin
|
BINDIR = bin
|
||||||
BIN=$(BINDIR)/$(NAME)
|
BIN = $(BINDIR)/$(NAME)
|
||||||
PREFIX=/usr
|
PREFIX = /usr
|
||||||
|
|
||||||
|
.PHONY: all prep build check-build freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64 compile install check-install uninstall clean
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
prep: clean
|
prep: clean
|
||||||
|
go mod init; go mod tidy
|
||||||
mkdir $(BINDIR)
|
mkdir $(BINDIR)
|
||||||
|
|
||||||
build: prep
|
build: prep
|
||||||
|
40
args.go
40
args.go
@ -3,7 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/juju/gnuflag"
|
"github.com/juju/gnuflag"
|
||||||
|
|
||||||
|
"range-gen/output"
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -16,12 +19,28 @@ var (
|
|||||||
|
|
||||||
ArgJobs int = 0
|
ArgJobs int = 0
|
||||||
ArgDefaultNoiseLevel int = 0
|
ArgDefaultNoiseLevel int = 0
|
||||||
|
|
||||||
|
ArgVersion bool = false
|
||||||
|
ArgHelp bool = false
|
||||||
)
|
)
|
||||||
|
|
||||||
func Use(vals ...interface{}) {
|
func printHelp() {
|
||||||
for _, val := range vals {
|
output.Println("Сreates a list of scene ranges based on a set of frames from the video")
|
||||||
_ = val
|
output.Println("")
|
||||||
}
|
output.Println("Usage: range-gen [option]... <input_dir> <output_file> <threshold>")
|
||||||
|
output.Println("input_dir Directory with png images")
|
||||||
|
output.Println("output_file Range list file")
|
||||||
|
output.Println("threshold Image similarity threshold (0-1024)")
|
||||||
|
output.Println("")
|
||||||
|
output.Println("Options:")
|
||||||
|
output.Println(" -j, --jobs N Allow N jobs at once")
|
||||||
|
output.Println(" -n, --noise Default noise level for each range")
|
||||||
|
output.Println(" -h, --help Show this page")
|
||||||
|
output.Println(" -v, --version Show version")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printVersion() {
|
||||||
|
output.Println("multini ", Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -29,11 +48,24 @@ func init() {
|
|||||||
gnuflag.IntVar(&ArgJobs, "j", 0, "")
|
gnuflag.IntVar(&ArgJobs, "j", 0, "")
|
||||||
gnuflag.IntVar(&ArgDefaultNoiseLevel, "noise", -1, "")
|
gnuflag.IntVar(&ArgDefaultNoiseLevel, "noise", -1, "")
|
||||||
gnuflag.IntVar(&ArgDefaultNoiseLevel, "n", -1, "")
|
gnuflag.IntVar(&ArgDefaultNoiseLevel, "n", -1, "")
|
||||||
|
gnuflag.BoolVar(&ArgVersion, "version", false, "")
|
||||||
|
gnuflag.BoolVar(&ArgVersion, "v", false, "")
|
||||||
|
gnuflag.BoolVar(&ArgHelp, "help", false, "")
|
||||||
|
gnuflag.BoolVar(&ArgHelp, "h", false, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArgs() error {
|
func parseArgs() error {
|
||||||
gnuflag.Parse(false)
|
gnuflag.Parse(false)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ArgHelp:
|
||||||
|
printHelp()
|
||||||
|
os.Exit(EXIT_SUCCESS)
|
||||||
|
case ArgVersion:
|
||||||
|
printVersion()
|
||||||
|
os.Exit(EXIT_SUCCESS)
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < 3 && i < gnuflag.NArg(); i++ {
|
for i := 0; i < 3 && i < gnuflag.NArg(); i++ {
|
||||||
switch i {
|
switch i {
|
||||||
case 0:
|
case 0:
|
||||||
|
10
go.mod
Normal file
10
go.mod
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module range-gen
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||||
|
github.com/dsoprea/go-perceptualhash v0.0.0-20200804060033-5ef3a3d0c14b
|
||||||
|
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
|
)
|
16
go.sum
Normal file
16
go.sum
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg=
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||||
|
github.com/dsoprea/go-perceptualhash v0.0.0-20200804060033-5ef3a3d0c14b h1:MvVsQ3fIkIpkUwphIPzjsuJGNjYQaPMAn7nXtet6Jcc=
|
||||||
|
github.com/dsoprea/go-perceptualhash v0.0.0-20200804060033-5ef3a3d0c14b/go.mod h1:mOZww7GHNRuvbz9vRejK7aGUgZU6Z+dleJ6PrFCDieE=
|
||||||
|
github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4=
|
||||||
|
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||||
|
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d h1:c93kUJDtVAXFEhsCh5jSxyOJmFHuzcihnslQiX8Urwo=
|
||||||
|
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
92
main.go
92
main.go
@ -5,9 +5,14 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
_ "image/png"
|
_ "image/png"
|
||||||
|
|
||||||
@ -25,12 +30,14 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
Version string = "dev"
|
||||||
|
|
||||||
hashes map[string]string
|
hashes map[string]string
|
||||||
names []string
|
names []string
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
output.SetEndOfLineNative()
|
closeHandler() // Ctrl+C
|
||||||
|
|
||||||
if err := parseArgs(); err != nil {
|
if err := parseArgs(); err != nil {
|
||||||
output.Errorln(err)
|
output.Errorln(err)
|
||||||
@ -49,19 +56,73 @@ func main() {
|
|||||||
os.Exit(EXIT_DIR_READ_ERR)
|
os.Exit(EXIT_DIR_READ_ERR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ArgJobs == 0 {
|
||||||
|
ArgJobs = runtime.NumCPU()
|
||||||
|
}
|
||||||
|
runtime.GOMAXPROCS(ArgJobs)
|
||||||
|
|
||||||
|
hashes, names := calcHashes(files)
|
||||||
|
|
||||||
|
ranges := calcRanges(hashes, names, Threshold)
|
||||||
|
|
||||||
|
writeRanges(ranges)
|
||||||
|
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
|
||||||
|
//wg.Add(1)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
os.Exit(EXIT_SUCCESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func closeHandler() {
|
||||||
|
interrupt := make(chan os.Signal, 2)
|
||||||
|
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
|
||||||
|
go func() {
|
||||||
|
<-interrupt
|
||||||
|
output.Println("Closed by SIGINT")
|
||||||
|
os.Exit(EXIT_SUCCESS)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcHashes(files []os.FileInfo) (map[string]string, []string) {
|
||||||
|
var hashes map[string]string
|
||||||
|
var keys []string
|
||||||
|
var err error
|
||||||
|
|
||||||
hashes = make(map[string]string)
|
hashes = make(map[string]string)
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if !file.IsDir() && strings.HasSuffix(file.Name(), ".png") {
|
if !file.IsDir() && strings.HasSuffix(file.Name(), ".png") {
|
||||||
names = append(names, file.Name())
|
keys = append(keys, file.Name())
|
||||||
hashes[file.Name()], err = calchash(ArgInput + file.Name())
|
hashes[file.Name()], err = calcHash(filepath.Join(ArgInput, file.Name()))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output.Errorln(err)
|
output.Errorln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(names)
|
sort.Strings(keys)
|
||||||
|
return hashes, keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcHash(filepath string) (string, error) {
|
||||||
|
file, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
image, _, err := image.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockhash.NewBlockhash(image, 16).Hexdigest(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcRanges(hashes map[string]string, names []string, Threshold int) string {
|
||||||
var ranges strings.Builder
|
var ranges strings.Builder
|
||||||
var prevHash string = ""
|
var prevHash string = ""
|
||||||
var dist int = 0
|
var dist int = 0
|
||||||
@ -86,12 +147,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
ranges.WriteString(startName + "\t" + names[len(names)-1] + rangeNoise + output.EOL())
|
ranges.WriteString(startName + "\t" + names[len(names)-1] + rangeNoise + output.EOL())
|
||||||
|
|
||||||
|
return ranges.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeRanges(ranges string) {
|
||||||
mode := os.FileMode(int(0644))
|
mode := os.FileMode(int(0644))
|
||||||
targetFile, err := os.OpenFile(ArgOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
targetFile, err := os.OpenFile(ArgOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||||
defer targetFile.Close()
|
defer targetFile.Close()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
datawriter := bufio.NewWriter(targetFile)
|
datawriter := bufio.NewWriter(targetFile)
|
||||||
_, err = datawriter.WriteString(ranges.String())
|
_, err = datawriter.WriteString(ranges)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = datawriter.Flush()
|
err = datawriter.Flush()
|
||||||
}
|
}
|
||||||
@ -101,23 +166,6 @@ func main() {
|
|||||||
output.Errorln(err)
|
output.Errorln(err)
|
||||||
os.Exit(EXIT_FILE_WRITE_ERR)
|
os.Exit(EXIT_FILE_WRITE_ERR)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(EXIT_SUCCESS)
|
|
||||||
}
|
|
||||||
|
|
||||||
func calchash(filepath string) (string, error) {
|
|
||||||
file, err := os.Open(filepath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
image, _, err := image.Decode(file)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockhash.NewBlockhash(image, 16).Hexdigest(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hammingDistance(prev, cur string) int {
|
func hammingDistance(prev, cur string) int {
|
||||||
|
@ -15,6 +15,10 @@ var (
|
|||||||
stderr *log.Logger = log.New(os.Stderr, "", 0)
|
stderr *log.Logger = log.New(os.Stderr, "", 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SetEndOfLineNative()
|
||||||
|
}
|
||||||
|
|
||||||
func SetQuiet(enabled bool) {
|
func SetQuiet(enabled bool) {
|
||||||
if enabled {
|
if enabled {
|
||||||
stdout = devNull
|
stdout = devNull
|
||||||
|
Loading…
x
Reference in New Issue
Block a user