Merge main

This commit is contained in:
Chigozirim Igweamaka 2025-04-01 18:08:54 +01:00
commit 2eb682ffe2
6 changed files with 106 additions and 64 deletions

View file

@ -297,9 +297,12 @@ func saveSong(filePath string, force bool) error {
return fmt.Errorf("failed to get YouTube ID for song: %v", err) return fmt.Errorf("failed to get YouTube ID for song: %v", err)
} }
fileName := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath))
if track.Title == "" { if track.Title == "" {
return fmt.Errorf("no title found in metadata") // If title is empty, use the file name
track.Title = fileName
} }
if track.Artist == "" { if track.Artist == "" {
return fmt.Errorf("no artist found in metadata") return fmt.Errorf("no artist found in metadata")
} }
@ -310,11 +313,10 @@ func saveSong(filePath string, force bool) error {
} }
// Move song in wav format to songs directory // Move song in wav format to songs directory
fileName := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath))
wavFile := fileName + ".wav" wavFile := fileName + ".wav"
sourcePath := filepath.Join(filepath.Dir(filePath), wavFile) sourcePath := filepath.Join(filepath.Dir(filePath), wavFile)
newFilePath := filepath.Join(SONGS_DIR, wavFile) newFilePath := filepath.Join(SONGS_DIR, wavFile)
err = os.Rename(sourcePath, newFilePath) err = utils.MoveFile(sourcePath, newFilePath)
if err != nil { if err != nil {
return fmt.Errorf("failed to rename temporary file to output file: %v", err) return fmt.Errorf("failed to rename temporary file to output file: %v", err)
} }

View file

@ -35,7 +35,7 @@ func createTables(db *sql.DB) error {
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL, title TEXT NOT NULL,
artist TEXT NOT NULL, artist TEXT NOT NULL,
ytID TEXT UNIQUE, ytID TEXT,
key TEXT NOT NULL UNIQUE key TEXT NOT NULL UNIQUE
); );
` `

View file

@ -307,7 +307,7 @@ func ProcessAndSaveSong(songFilePath, songTitle, songArtist, ytID string) error
err = dbclient.StoreFingerprints(fingerprints) err = dbclient.StoreFingerprints(fingerprints)
if err != nil { if err != nil {
dbclient.DeleteSongByID(songID) dbclient.DeleteSongByID(songID)
return fmt.Errorf("error to storing fingerpring: %v", err) return fmt.Errorf("error to storing fingerprint: %v", err)
} }
fmt.Printf("Fingerprint for %v by %v saved in DB successfully\n", songTitle, songArtist) fmt.Printf("Fingerprint for %v by %v saved in DB successfully\n", songTitle, songArtist)

View file

@ -1,18 +1,10 @@
package utils package utils
import ( import (
"context"
"encoding/base64"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"log/slog" "io"
"os" "os"
"song-recognition/models"
"song-recognition/wav"
"strings"
"time"
"github.com/mdobak/go-xerrors"
) )
func DeleteFile(filePath string) error { func DeleteFile(filePath string) error {
@ -32,6 +24,36 @@ func CreateFolder(folderPath string) error {
return nil return nil
} }
func MoveFile(sourcePath string, destinationPath string) error {
srcFile, err := os.Open(sourcePath)
if err != nil {
return err
}
destFile, err := os.Create(destinationPath)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, srcFile)
if err != nil {
return err
}
err = srcFile.Close()
if err != nil {
return err
}
err = os.Remove(sourcePath)
if err != nil {
return err
}
return nil
}
func FloatsToBytes(data []float64, bitsPerSample int) ([]byte, error) { func FloatsToBytes(data []float64, bitsPerSample int) ([]byte, error) {
var byteData []byte var byteData []byte
@ -68,52 +90,3 @@ func FloatsToBytes(data []float64, bitsPerSample int) ([]byte, error) {
return byteData, nil return byteData, nil
} }
func ProcessRecording(recData *models.RecordData, saveRecording bool) ([]float64, error) {
decodedAudioData, err := base64.StdEncoding.DecodeString(recData.Audio)
if err != nil {
return nil, err
}
now := time.Now()
fileName := fmt.Sprintf("%04d_%02d_%02d_%02d_%02d_%02d.wav",
now.Second(), now.Minute(), now.Hour(),
now.Day(), now.Month(), now.Year(),
)
filePath := "tmp/" + fileName
err = wav.WriteWavFile(filePath, decodedAudioData, recData.SampleRate, recData.Channels, recData.SampleSize)
if err != nil {
return nil, err
}
reformatedWavFile, err := wav.ReformatWAV(filePath, 1)
if err != nil {
return nil, err
}
wavInfo, _ := wav.ReadWavInfo(reformatedWavFile)
samples, _ := wav.WavBytesToSamples(wavInfo.Data)
if saveRecording {
logger := GetLogger()
ctx := context.Background()
err := CreateFolder("recordings")
if err != nil {
err := xerrors.New(err)
logger.ErrorContext(ctx, "Failed create folder.", slog.Any("error", err))
}
newFilePath := strings.Replace(reformatedWavFile, "tmp/", "recordings/", 1)
err = os.Rename(reformatedWavFile, newFilePath)
if err != nil {
logger.ErrorContext(ctx, "Failed to move file.", slog.Any("error", err))
}
}
DeleteFile(fileName)
DeleteFile(reformatedWavFile)
return samples, nil
}

View file

@ -5,6 +5,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"song-recognition/utils"
"strings" "strings"
) )
@ -43,7 +44,7 @@ func ConvertToWAV(inputFilePath string, channels int) (wavFilePath string, err e
} }
// Rename the temporary file to the output file // Rename the temporary file to the output file
err = os.Rename(tmpFile, outputFile) err = utils.MoveFile(tmpFile, outputFile)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to rename temporary file to output file: %v", err) return "", fmt.Errorf("failed to rename temporary file to output file: %v", err)
} }

View file

@ -2,13 +2,22 @@ package wav
import ( import (
"bytes" "bytes"
"context"
"encoding/base64"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log/slog"
"os" "os"
"os/exec" "os/exec"
"song-recognition/models"
"song-recognition/utils"
"strings"
"time"
"github.com/mdobak/go-xerrors"
) )
// WavHeader defines the structure of a WAV header // WavHeader defines the structure of a WAV header
@ -198,5 +207,62 @@ func GetMetadata(filePath string) (FFmpegMetadata, error) {
return metadata, err return metadata, err
} }
// convert all keys of the Tags map to lowercase
for k, v := range metadata.Format.Tags {
metadata.Format.Tags[strings.ToLower(k)] = v
}
for k, v := range metadata.Streams[0].Tags {
metadata.Streams[0].Tags[strings.ToLower(k)] = v
}
return metadata, nil return metadata, nil
} }
func ProcessRecording(recData *models.RecordData, saveRecording bool) ([]float64, error) {
decodedAudioData, err := base64.StdEncoding.DecodeString(recData.Audio)
if err != nil {
return nil, err
}
now := time.Now()
fileName := fmt.Sprintf("%04d_%02d_%02d_%02d_%02d_%02d.wav",
now.Second(), now.Minute(), now.Hour(),
now.Day(), now.Month(), now.Year(),
)
filePath := "tmp/" + fileName
err = WriteWavFile(filePath, decodedAudioData, recData.SampleRate, recData.Channels, recData.SampleSize)
if err != nil {
return nil, err
}
reformatedWavFile, err := ReformatWAV(filePath, 1)
if err != nil {
return nil, err
}
wavInfo, _ := ReadWavInfo(reformatedWavFile)
samples, _ := WavBytesToSamples(wavInfo.Data)
if saveRecording {
logger := utils.GetLogger()
ctx := context.Background()
err := utils.CreateFolder("recordings")
if err != nil {
err := xerrors.New(err)
logger.ErrorContext(ctx, "Failed create folder.", slog.Any("error", err))
}
newFilePath := strings.Replace(reformatedWavFile, "tmp/", "recordings/", 1)
err = os.Rename(reformatedWavFile, newFilePath)
if err != nil {
logger.ErrorContext(ctx, "Failed to move file.", slog.Any("error", err))
}
}
utils.DeleteFile(fileName)
utils.DeleteFile(reformatedWavFile)
return samples, nil
}