✨ Tag files
This commit is contained in:
parent
7a198a0273
commit
ed7e1ddade
8 changed files with 172 additions and 4 deletions
|
|
@ -20,6 +20,7 @@ func PickNewFile() media.Probe {
|
|||
}
|
||||
|
||||
func SetFile(path string) media.Probe {
|
||||
resetTags()
|
||||
f := media.ProbeFile(path)
|
||||
file = &f
|
||||
copyTagsFromFile()
|
||||
|
|
@ -71,6 +72,7 @@ func PickAgain() {
|
|||
}
|
||||
file = nil
|
||||
tmpfile = nil
|
||||
resetTags()
|
||||
}
|
||||
|
||||
func Finish() {
|
||||
|
|
|
|||
16
app/convert.go
Normal file
16
app/convert.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"codeberg.org/danjones000/strip-beats/media"
|
||||
"codeberg.org/danjones000/strip-beats/utils"
|
||||
)
|
||||
|
||||
func convert() {
|
||||
in := utils.Tern(tmpfile == nil, file, tmpfile)
|
||||
out, _ := media.ConvertAndTag(*in, tags)
|
||||
fmt.Println(out)
|
||||
|
||||
quit()
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package app
|
|||
|
||||
import (
|
||||
"os"
|
||||
p "path/filepath"
|
||||
s "strings"
|
||||
|
||||
"codeberg.org/danjones000/strip-beats/media"
|
||||
"codeberg.org/danjones000/strip-beats/utils"
|
||||
|
|
@ -31,7 +33,10 @@ func validateNumber(input string, lastChar rune) bool {
|
|||
}
|
||||
|
||||
func fadeFile() error {
|
||||
tmp, err := os.CreateTemp("", "audio.*.mka")
|
||||
base := p.Base(file.Format.Path)
|
||||
ext := p.Ext(base)
|
||||
base = s.TrimSuffix(base, ext)
|
||||
tmp, err := os.CreateTemp("", base+".*.mka")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
11
app/menu.go
11
app/menu.go
|
|
@ -10,7 +10,7 @@ func (st AppStep) Title() string {
|
|||
mustpick := "You need to pick a file"
|
||||
switch st {
|
||||
case Pick:
|
||||
return "Pick a new show"
|
||||
return "Pick a new file"
|
||||
case Watch:
|
||||
if file == nil {
|
||||
return mustpick
|
||||
|
|
@ -26,6 +26,11 @@ func (st AppStep) Title() string {
|
|||
return mustpick
|
||||
}
|
||||
return fmt.Sprintf("Should we try to identify %s", file.ShortPath())
|
||||
case Convert:
|
||||
if file == nil {
|
||||
return mustpick
|
||||
}
|
||||
return fmt.Sprintf("Convert %s?", file.ShortPath())
|
||||
case Restart:
|
||||
return "Forget current selection"
|
||||
case Quit:
|
||||
|
|
@ -54,6 +59,8 @@ func (st AppStep) Rune() rune {
|
|||
return 'r'
|
||||
case Print:
|
||||
return 'a'
|
||||
case Convert:
|
||||
return 'c'
|
||||
case Quit:
|
||||
return 'q'
|
||||
default:
|
||||
|
|
@ -70,7 +77,7 @@ func mainMenu() AppStep {
|
|||
if file == nil {
|
||||
steps = []list.Option{Pick, Quit}
|
||||
} else {
|
||||
steps = []list.Option{Pick, Watch, Fade, Print, Quit}
|
||||
steps = []list.Option{Pick, Watch, Fade, Print, Convert, Quit}
|
||||
}
|
||||
|
||||
step := list.List("What would you like to do next?", steps, nil)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const (
|
|||
Watch
|
||||
Fade
|
||||
Print
|
||||
Convert
|
||||
Restart
|
||||
Quit
|
||||
)
|
||||
|
|
@ -94,6 +95,9 @@ func Run(step AppStep) {
|
|||
case Print:
|
||||
print()
|
||||
step = mainMenu()
|
||||
case Convert:
|
||||
convert()
|
||||
step = mainMenu()
|
||||
case Quit:
|
||||
quit()
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ import (
|
|||
|
||||
var tags t.Tags
|
||||
|
||||
func resetTags() {
|
||||
tags = t.Tags{}
|
||||
}
|
||||
|
||||
func copyTagsFromFile() {
|
||||
if file == nil {
|
||||
panic(errors.New("Missing file"))
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
const (
|
||||
AppName string = "strip-beats"
|
||||
Version string = "0.1.0"
|
||||
Version string = "0.1.1"
|
||||
Url string = "https://codeberg.org/danjones000/strip-beats"
|
||||
Email string = "danjones@goodevilgenius.org"
|
||||
UserAgent string = AppName + "/" + Version + " (" + Url + "; " + Email + ")"
|
||||
|
|
|
|||
130
media/ffmpeg.go
130
media/ffmpeg.go
|
|
@ -3,12 +3,142 @@ package media
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
p "path/filepath"
|
||||
"strconv"
|
||||
s "strings"
|
||||
|
||||
"codeberg.org/danjones000/strip-beats/config"
|
||||
t "codeberg.org/danjones000/strip-beats/media/tags"
|
||||
"codeberg.org/danjones000/strip-beats/utils"
|
||||
"github.com/google/uuid"
|
||||
ffmpeg "github.com/u2takey/ffmpeg-go"
|
||||
)
|
||||
|
||||
func ConvertAndTag(in Probe, tags t.Tags) (string, error) {
|
||||
st := in.GetFirstAcceptableAudio()
|
||||
if st == nil {
|
||||
st = in.GetFirstAudio()
|
||||
}
|
||||
if st == nil {
|
||||
return "", errors.New("Can't find an audio stream")
|
||||
}
|
||||
|
||||
conf := config.GetConfig()
|
||||
codec := utils.Tern(st.isAcceptableCodec(), "copy", conf.FfEncoder)
|
||||
target := utils.Tern(st.isAcceptableCodec(), st.CodecName, conf.Codec)
|
||||
|
||||
base := p.Base(in.Format.Path)
|
||||
ext := p.Ext(base)
|
||||
base = s.TrimSuffix(base, ext)
|
||||
ext = conf.CodecExt[target]
|
||||
|
||||
out := p.Join(conf.SavePath, base+"."+ext)
|
||||
|
||||
input := ffmpeg.Input(in.Format.Path).Get(strconv.Itoa(st.Index))
|
||||
args := ffmpeg.KwArgs{"c:a": codec}
|
||||
output := input.Output(out, args, getMetadataArgs(ext, tags)).GlobalArgs("-y")
|
||||
|
||||
return out, output.Run()
|
||||
}
|
||||
|
||||
func getMetadataArgs(ext string, tags t.Tags) ffmpeg.KwArgs {
|
||||
var meta []string
|
||||
args := ffmpeg.KwArgs{}
|
||||
switch ext {
|
||||
case "opus":
|
||||
fallthrough
|
||||
case "flac":
|
||||
fallthrough
|
||||
case "ogg":
|
||||
meta = append(meta, mapMetaKeys(getOggMeta(tags))...)
|
||||
case "m4a":
|
||||
fallthrough
|
||||
case "mp4":
|
||||
meta = append(meta, mapMetaKeys(getMp4Meta(tags))...)
|
||||
case "mp3":
|
||||
// @todo meta = append(meta, mapMetaKeys(getMp3Meta(tags))...)
|
||||
}
|
||||
|
||||
meta = append(meta, "comment=Processed by "+config.UserAgent)
|
||||
args["metadata"] = meta
|
||||
return args
|
||||
}
|
||||
|
||||
func mapMetaKeys(meta map[string]string) []string {
|
||||
out := []string{}
|
||||
for k, v := range meta {
|
||||
if v != "" {
|
||||
out = append(out, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func getOggMeta(tags t.Tags) map[string]string {
|
||||
meta := map[string]string{}
|
||||
meta["TITLE"] = tags.Title
|
||||
meta["ARTIST"] = tags.Artist
|
||||
meta["ALBUM_ARTIST"] = tags.AlbumArtist
|
||||
meta["ALBUMARTIST"] = tags.AlbumArtist
|
||||
meta["ALBUM"] = tags.Album
|
||||
meta["DATE"] = tags.Date
|
||||
year, _, _ := s.Cut(tags.Date, "-")
|
||||
meta["YEAR"] = year
|
||||
meta["URL"] = tags.Url
|
||||
meta["PURL"] = tags.Url
|
||||
meta["URI"] = tags.Url
|
||||
meta["ARTISTSORT"] = tags.ArtistSort
|
||||
meta["ALBUMARTISTSORT"] = tags.AlbumArtistSort
|
||||
meta["RELEASECOUNTRY"] = tags.ReleaseCountry
|
||||
meta["LABEL"] = tags.Label
|
||||
meta["GENRE"] = tags.Genre
|
||||
meta["DISC"] = utils.Tern(tags.Disc > 0, strconv.Itoa(tags.Disc), "")
|
||||
meta["DISCTOTAL"] = utils.Tern(tags.DiscCount > 0, strconv.Itoa(tags.DiscCount), "")
|
||||
meta["TRACK"] = utils.Tern(tags.Track > 0, strconv.Itoa(tags.Track), "")
|
||||
meta["TRACKTOTAL"] = utils.Tern(tags.TrackCount > 0, strconv.Itoa(tags.TrackCount), "")
|
||||
if tags.AcoustidId != uuid.Nil {
|
||||
meta["ACOUSTID_ID"] = tags.AcoustidId.String()
|
||||
}
|
||||
if tags.MusicbrainzReleaseGroupId != uuid.Nil {
|
||||
meta["MUSICBRAINZ_RELEASEGROUPID"] = tags.MusicbrainzReleaseGroupId.String()
|
||||
}
|
||||
if tags.MusicbrainzAlbumId != uuid.Nil {
|
||||
meta["MUSICBRAINZ_ALBUMID"] = tags.MusicbrainzAlbumId.String()
|
||||
}
|
||||
if tags.MusicbrainzAlbumArtistId != uuid.Nil {
|
||||
meta["MUSICBRAINZ_ALBUMARTISTID"] = tags.MusicbrainzAlbumArtistId.String()
|
||||
}
|
||||
if tags.MusicbrainzRecordingId != uuid.Nil {
|
||||
meta["MUSICBRAINZ_RECORDINGID"] = tags.MusicbrainzRecordingId.String()
|
||||
}
|
||||
if tags.MusicBrainzLabelId != uuid.Nil {
|
||||
meta["MUSICBRAINZ_LABELID"] = tags.MusicBrainzLabelId.String()
|
||||
}
|
||||
|
||||
return meta
|
||||
}
|
||||
|
||||
func getMp4Meta(tags t.Tags) map[string]string {
|
||||
meta := map[string]string{}
|
||||
meta["title"] = tags.Title
|
||||
meta["artist"] = tags.Artist
|
||||
meta["album_artist"] = tags.AlbumArtist
|
||||
meta["album"] = tags.Album
|
||||
year, _, _ := s.Cut(tags.Date, "-")
|
||||
meta["year"] = year
|
||||
meta["description"] = tags.Url
|
||||
meta["genre"] = tags.Genre
|
||||
meta["network"] = tags.Label
|
||||
if tags.Disc > 0 {
|
||||
meta["disc"] = fmt.Sprintf("%d", tags.Disc) + utils.Tern(tags.DiscCount > 0, fmt.Sprintf("/%d", tags.DiscCount), "")
|
||||
}
|
||||
if tags.Track > 0 {
|
||||
meta["track"] = fmt.Sprintf("%d", tags.Track) + utils.Tern(tags.TrackCount > 0, fmt.Sprintf("/%d", tags.TrackCount), "")
|
||||
}
|
||||
|
||||
return meta
|
||||
}
|
||||
|
||||
func TrimWithFade(in Probe, out string, start, stop, up, down float64) error {
|
||||
// -ss (start) -t (end) -af afade=t=in:st=(start):d=(up),afade=t=out:st=(downstart):d=(down)
|
||||
st := in.GetFirstAcceptableAudio()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue