mirror of
https://github.com/cgzirim/seek-tune.git
synced 2025-12-17 08:54:19 +00:00
A couple more changes
This commit is contained in:
parent
a1ba649480
commit
439b5442f5
7 changed files with 214 additions and 108 deletions
|
|
@ -13,6 +13,16 @@ function App() {
|
||||||
const [serverEngaged, setServerEngaged] = useState(false);
|
const [serverEngaged, setServerEngaged] = useState(false);
|
||||||
const [peerConnection, setPeerConnection] = useState();
|
const [peerConnection, setPeerConnection] = useState();
|
||||||
|
|
||||||
|
function cleanUp() {
|
||||||
|
if (stream != null) {
|
||||||
|
stream.getTracks().forEach((track) => track.stop());
|
||||||
|
}
|
||||||
|
setOffer(null);
|
||||||
|
setStream(null);
|
||||||
|
setPeerConnection(null);
|
||||||
|
setServerEngaged(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Function to initiate the client peer
|
// Function to initiate the client peer
|
||||||
function initiateClientPeer(stream = null) {
|
function initiateClientPeer(stream = null) {
|
||||||
const peer = new Peer({
|
const peer = new Peer({
|
||||||
|
|
@ -71,8 +81,13 @@ function App() {
|
||||||
|
|
||||||
socket.on("matches", (matches) => {
|
socket.on("matches", (matches) => {
|
||||||
matches = JSON.parse(matches);
|
matches = JSON.parse(matches);
|
||||||
setMatches(matches);
|
if (matches) {
|
||||||
console.log("Matches: ", matches);
|
setMatches(matches);
|
||||||
|
console.log("Matches: ", matches);
|
||||||
|
} else {
|
||||||
|
console.log("No Matches");
|
||||||
|
}
|
||||||
|
cleanUp();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("downloadStatus", (msg) => {
|
socket.on("downloadStatus", (msg) => {
|
||||||
|
|
@ -87,6 +102,20 @@ function App() {
|
||||||
console.log("Playlist stat: ", msg);
|
console.log("Playlist stat: ", msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const emitTotalSongs = () => {
|
||||||
|
socket.emit("totalSongs", "");
|
||||||
|
};
|
||||||
|
|
||||||
|
const intervalId = setInterval(emitTotalSongs, 8000);
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
socket.on("totalSongs", (totalSongs) => {
|
||||||
|
console.log("Total songs in DB: ", totalSongs);
|
||||||
|
});
|
||||||
|
|
||||||
const streamAudio = () => {
|
const streamAudio = () => {
|
||||||
navigator.mediaDevices
|
navigator.mediaDevices
|
||||||
.getDisplayMedia({ audio: true })
|
.getDisplayMedia({ audio: true })
|
||||||
|
|
@ -109,7 +138,7 @@ function App() {
|
||||||
setOffer(JSON.stringify(data));
|
setOffer(JSON.stringify(data));
|
||||||
console.log("Offer should be reset");
|
console.log("Offer should be reset");
|
||||||
});
|
});
|
||||||
setStream(stream); // Set the audio stream to state
|
setStream(stream);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Error accessing user media:", error);
|
console.error("Error accessing user media:", error);
|
||||||
|
|
|
||||||
176
server.go
176
server.go
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"song-recognition/signal"
|
"song-recognition/signal"
|
||||||
"song-recognition/spotify"
|
"song-recognition/spotify"
|
||||||
|
"song-recognition/utils"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -43,9 +44,10 @@ func main() {
|
||||||
|
|
||||||
server := socketio.NewServer(nil)
|
server := socketio.NewServer(nil)
|
||||||
|
|
||||||
server.OnConnect("/", func(s socketio.Conn) error {
|
server.OnConnect("/", func(socket socketio.Conn) error {
|
||||||
s.SetContext("")
|
socket.SetContext("")
|
||||||
log.Println("CONNECTED: ", s.ID())
|
log.Println("CONNECTED: ", socket.ID())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -56,72 +58,21 @@ func main() {
|
||||||
s.Emit("initAnswer", signal.Encode(*peerConnection.LocalDescription()))
|
s.Emit("initAnswer", signal.Encode(*peerConnection.LocalDescription()))
|
||||||
})
|
})
|
||||||
|
|
||||||
server.OnEvent("/", "engage", func(s socketio.Conn, encodedOffer string) {
|
server.OnEvent("/", "totalSongs", func(socket socketio.Conn) {
|
||||||
log.Println("engage: ", encodedOffer)
|
db, err := utils.NewDbClient()
|
||||||
|
|
||||||
peerConnection := signal.SetupWebRTC(encodedOffer)
|
|
||||||
|
|
||||||
// Allow us to receive 1 audio track
|
|
||||||
if _, err := peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a handler for when a new remote track starts, this handler saves buffers to disk as
|
|
||||||
// an Ogg file.
|
|
||||||
oggFile, err := oggwriter.New("output.ogg", 44100, 1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Printf("Error connecting to DB: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
totalSongs, err := db.TotalSongs()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Log error getting total songs count:", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
socket.Emit("totalSongs", totalSongs)
|
||||||
codec := track.Codec()
|
|
||||||
if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) {
|
|
||||||
fmt.Println("Got Opus track, saving to disk as output.opus (44.1 kHz, 1 channel)")
|
|
||||||
// signal.SaveToDisk(oggFile, track)
|
|
||||||
// TODO turn match to json here
|
|
||||||
matches, err := signal.MatchSampleAudio(track)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonData, err := json.Marshal(matches[:5])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Log error: ", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(jsonData))
|
|
||||||
|
|
||||||
s.Emit("matches", string(jsonData))
|
|
||||||
peerConnection.Close()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Set the handler for ICE connection state
|
|
||||||
// This will notify you when the peer has connected/disconnected
|
|
||||||
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
|
|
||||||
fmt.Printf("Connection State has changed %s \n", connectionState.String())
|
|
||||||
|
|
||||||
if connectionState == webrtc.ICEConnectionStateConnected {
|
|
||||||
fmt.Println("Ctrl+C the remote client to stop the demo")
|
|
||||||
} else if connectionState == webrtc.ICEConnectionStateFailed || connectionState == webrtc.ICEConnectionStateClosed {
|
|
||||||
if closeErr := oggFile.Close(); closeErr != nil {
|
|
||||||
panic(closeErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Done writing media files")
|
|
||||||
|
|
||||||
// Gracefully shutdown the peer connection
|
|
||||||
if closeErr := peerConnection.Close(); closeErr != nil {
|
|
||||||
panic(closeErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// os.Exit(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Emit answer in base64
|
|
||||||
s.Emit("serverEngaged", signal.Encode(*peerConnection.LocalDescription()))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
server.OnEvent("/", "newDownload", func(socket socketio.Conn, spotifyURL string) {
|
server.OnEvent("/", "newDownload", func(socket socketio.Conn, spotifyURL string) {
|
||||||
|
|
@ -178,13 +129,31 @@ func main() {
|
||||||
socket.Emit("downloadStatus", fmt.Sprintf("%d songs downloaded from playlist", totalTracksDownloaded))
|
socket.Emit("downloadStatus", fmt.Sprintf("%d songs downloaded from playlist", totalTracksDownloaded))
|
||||||
|
|
||||||
} else if strings.Contains(spotifyURL, "track") {
|
} else if strings.Contains(spotifyURL, "track") {
|
||||||
// check if track already exist
|
|
||||||
trackInfo, err := spotify.TrackInfo(spotifyURL)
|
trackInfo, err := spotify.TrackInfo(spotifyURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("log error: ", err)
|
fmt.Println("log error: ", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if track already exist
|
||||||
|
db, err := utils.NewDbClient()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("Log - error connecting to DB: %d", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
chunkTag, err := db.GetChunkTagForSong(trackInfo.Title, trackInfo.Artist)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("chunkTag error: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if chunkTag != nil {
|
||||||
|
socket.Emit("downloadStatus", fmt.Sprintf(
|
||||||
|
"'%s' by '%s' already exists in the database (https://www.youtube.com/watch?v=%s)",
|
||||||
|
trackInfo.Title, trackInfo.Artist, chunkTag["youtubeid"]))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = spotify.DlSingleTrack(spotifyURL, tmpSongDir)
|
err = spotify.DlSingleTrack(spotifyURL, tmpSongDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
socket.Emit("downloadStatus", fmt.Sprintf("Failed to download '%s' by '%s'", trackInfo.Title, trackInfo.Artist))
|
socket.Emit("downloadStatus", fmt.Sprintf("Failed to download '%s' by '%s'", trackInfo.Title, trackInfo.Artist))
|
||||||
|
|
@ -199,6 +168,79 @@ func main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
server.OnEvent("/", "engage", func(s socketio.Conn, encodedOffer string) {
|
||||||
|
log.Println("engage: ", encodedOffer)
|
||||||
|
|
||||||
|
peerConnection := signal.SetupWebRTC(encodedOffer)
|
||||||
|
|
||||||
|
// Allow us to receive 1 audio track
|
||||||
|
if _, err := peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a handler for when a new remote track starts, this handler saves buffers to disk as
|
||||||
|
// an Ogg file.
|
||||||
|
oggFile, err := oggwriter.New("output.ogg", 44100, 1)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
|
codec := track.Codec()
|
||||||
|
if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) {
|
||||||
|
fmt.Println("Got Opus track, saving to disk as output.opus (44.1 kHz, 1 channel)")
|
||||||
|
// signal.SaveToDisk(oggFile, track)
|
||||||
|
// TODO turn match to json here
|
||||||
|
matches, err := signal.MatchSampleAudio(track)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(matches)
|
||||||
|
|
||||||
|
if len(matches) > 5 {
|
||||||
|
jsonData, err = json.Marshal(matches[:5])
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Log error: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(jsonData))
|
||||||
|
|
||||||
|
s.Emit("matches", string(jsonData))
|
||||||
|
peerConnection.Close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set the handler for ICE connection state
|
||||||
|
// This will notify you when the peer has connected/disconnected
|
||||||
|
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
|
||||||
|
fmt.Printf("Connection State has changed %s \n", connectionState.String())
|
||||||
|
|
||||||
|
if connectionState == webrtc.ICEConnectionStateConnected {
|
||||||
|
fmt.Println("Ctrl+C the remote client to stop the demo")
|
||||||
|
} else if connectionState == webrtc.ICEConnectionStateFailed || connectionState == webrtc.ICEConnectionStateClosed {
|
||||||
|
if closeErr := oggFile.Close(); closeErr != nil {
|
||||||
|
panic(closeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Done writing media files")
|
||||||
|
|
||||||
|
// Gracefully shutdown the peer connection
|
||||||
|
if closeErr := peerConnection.Close(); closeErr != nil {
|
||||||
|
panic(closeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// os.Exit(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Emit answer in base64
|
||||||
|
s.Emit("serverEngaged", signal.Encode(*peerConnection.LocalDescription()))
|
||||||
|
})
|
||||||
|
|
||||||
server.OnError("/", func(s socketio.Conn, e error) {
|
server.OnError("/", func(s socketio.Conn, e error) {
|
||||||
log.Println("meet error:", e)
|
log.Println("meet error:", e)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChunkTag struct {
|
type ChunkTag struct {
|
||||||
SongName string
|
SongTitle string
|
||||||
SongArtist string
|
SongArtist string
|
||||||
YouTubeID string
|
YouTubeID string
|
||||||
TimeStamp string
|
TimeStamp string
|
||||||
|
|
@ -45,14 +45,14 @@ func Match(sampleAudio []byte) ([]primitive.M, error) {
|
||||||
var chunkTags = make(map[string]primitive.M)
|
var chunkTags = make(map[string]primitive.M)
|
||||||
var songsTimestamps = make(map[string][]string)
|
var songsTimestamps = make(map[string][]string)
|
||||||
for _, chunkfgp := range chunkFingerprints {
|
for _, chunkfgp := range chunkFingerprints {
|
||||||
listOfChunkTags, err := db.GetChunkData(chunkfgp)
|
listOfChunkTags, err := db.GetChunkTags(chunkfgp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting chunk data with fingerprint %d: %v", chunkfgp, err)
|
return nil, fmt.Errorf("error getting chunk data with fingerprint %d: %v", chunkfgp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, chunkTag := range listOfChunkTags {
|
for _, chunkTag := range listOfChunkTags {
|
||||||
timeStamp := fmt.Sprint(chunkTag["timestamp"])
|
timeStamp := fmt.Sprint(chunkTag["timestamp"])
|
||||||
songKey := fmt.Sprintf("%s by %s", chunkTag["songname"], chunkTag["songartist"])
|
songKey := fmt.Sprintf("%s by %s", chunkTag["songtitle"], chunkTag["songartist"])
|
||||||
|
|
||||||
if songsTimestamps[songKey] == nil {
|
if songsTimestamps[songKey] == nil {
|
||||||
songsTimestamps[songKey] = []string{timeStamp}
|
songsTimestamps[songKey] = []string{timeStamp}
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ func correctFilename(title, artist string) (string, string) {
|
||||||
return title, artist
|
return title, artist
|
||||||
}
|
}
|
||||||
|
|
||||||
func processAndSaveSong(m4aFile, songName, songArtist, ytID string) error {
|
func processAndSaveSong(m4aFile, songTitle, songArtist, ytID string) error {
|
||||||
db, err := utils.NewDbClient()
|
db, err := utils.NewDbClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error connecting to DB: %d", err)
|
return fmt.Errorf("error connecting to DB: %d", err)
|
||||||
|
|
@ -316,7 +316,7 @@ func processAndSaveSong(m4aFile, songName, songArtist, ytID string) error {
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Check if the song has been processed and saved before
|
// Check if the song has been processed and saved before
|
||||||
songKey := fmt.Sprintf("%s - %s", songName, songArtist)
|
songKey := fmt.Sprintf("%s - %s", songTitle, songArtist)
|
||||||
songExists, err := db.SongExists(songKey)
|
songExists, err := db.SongExists(songKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error checking if song exists: %v", err)
|
return fmt.Errorf("error checking if song exists: %v", err)
|
||||||
|
|
@ -345,10 +345,10 @@ func processAndSaveSong(m4aFile, songName, songArtist, ytID string) error {
|
||||||
lines := strings.Split(string(output), "\n")
|
lines := strings.Split(string(output), "\n")
|
||||||
// bitDepth, _ := strconv.Atoi(strings.TrimSpace(lines[1]))
|
// bitDepth, _ := strconv.Atoi(strings.TrimSpace(lines[1]))
|
||||||
sampleRate, _ := strconv.Atoi(strings.TrimSpace(lines[0]))
|
sampleRate, _ := strconv.Atoi(strings.TrimSpace(lines[0]))
|
||||||
fmt.Printf("SAMPLE RATE for %s: %v", songName, sampleRate)
|
fmt.Printf("SAMPLE RATE for %s: %v", songTitle, sampleRate)
|
||||||
|
|
||||||
chunkTag := shazam.ChunkTag{
|
chunkTag := shazam.ChunkTag{
|
||||||
SongName: songName,
|
SongTitle: songTitle,
|
||||||
SongArtist: songArtist,
|
SongArtist: songArtist,
|
||||||
YouTubeID: ytID,
|
YouTubeID: ytID,
|
||||||
}
|
}
|
||||||
|
|
@ -358,8 +358,8 @@ func processAndSaveSong(m4aFile, songName, songArtist, ytID string) error {
|
||||||
_, fingerprints := shazam.FingerprintChunks(chunks, &chunkTag)
|
_, fingerprints := shazam.FingerprintChunks(chunks, &chunkTag)
|
||||||
|
|
||||||
// Save fingerprints to MongoDB
|
// Save fingerprints to MongoDB
|
||||||
for fgp, chunkData := range fingerprints {
|
for fgp, ctag := range fingerprints {
|
||||||
err := db.InsertChunkData(fgp, chunkData)
|
err := db.InsertChunkTag(fgp, ctag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error inserting document: %v", err)
|
return fmt.Errorf("error inserting document: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,6 @@ func TrackInfo(url string) (*Track, error) {
|
||||||
Album: gjson.Get(jsonResponse, "data.trackUnion.albumOfTrack.name").String(),
|
Album: gjson.Get(jsonResponse, "data.trackUnion.albumOfTrack.name").String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("ARTISTS: ", allArtists)
|
|
||||||
fmt.Println("TRACK: ", track)
|
|
||||||
|
|
||||||
return track.buildTrack(), nil
|
return track.buildTrack(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,9 +236,11 @@ func jsonList(resourceType, id string, offset, limit int64) (string, error) {
|
||||||
|
|
||||||
func (t *Track) buildTrack() *Track {
|
func (t *Track) buildTrack() *Track {
|
||||||
track := &Track{
|
track := &Track{
|
||||||
Title: t.Title,
|
Title: t.Title,
|
||||||
Artist: t.Artist,
|
Artist: t.Artist,
|
||||||
Album: t.Album,
|
Artists: t.Artists,
|
||||||
|
Duration: t.Duration,
|
||||||
|
Album: t.Album,
|
||||||
}
|
}
|
||||||
|
|
||||||
return track
|
return track
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import (
|
||||||
const developerKey = "AIzaSyC3nBFKqudeMItXnYKEeOUryLKhXnqBL7M"
|
const developerKey = "AIzaSyC3nBFKqudeMItXnYKEeOUryLKhXnqBL7M"
|
||||||
|
|
||||||
// https://github.com/BharatKalluri/spotifydl/blob/v0.1.0/src/youtube.go
|
// https://github.com/BharatKalluri/spotifydl/blob/v0.1.0/src/youtube.go
|
||||||
func VideoID(spTrack Track) (string, error) {
|
func getYoutubeIdWithAPI(spTrack Track) (string, error) {
|
||||||
service, err := youtube.NewService(context.TODO(), option.WithAPIKey(developerKey))
|
service, err := youtube.NewService(context.TODO(), option.WithAPIKey(developerKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error creating new YouTube client: %v", err)
|
log.Fatalf("Error creating new YouTube client: %v", err)
|
||||||
|
|
@ -77,10 +77,9 @@ func convertStringDurationToSeconds(durationStr string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetYoutubeId takes the query as string and returns the search results video ID's
|
// GetYoutubeId takes the query as string and returns the search results video ID's
|
||||||
func GetYoutubeId(spTrack Track) (string, error) {
|
func GetYoutubeId(track Track) (string, error) {
|
||||||
artists := strings.Join(spTrack.Artists, ", ")
|
songDurationInSeconds := track.Duration * 60
|
||||||
songDurationInSeconds := spTrack.Duration * 60
|
searchQuery := fmt.Sprintf("'%s' %s %s", track.Title, track.Artist, track.Album)
|
||||||
searchQuery := fmt.Sprintf("'%s' %s %s", spTrack.Title, artists, spTrack.Album)
|
|
||||||
|
|
||||||
searchResults, err := ytSearch(searchQuery, 10)
|
searchResults, err := ytSearch(searchQuery, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -99,6 +98,7 @@ func GetYoutubeId(spTrack Track) (string, error) {
|
||||||
return result.ID, nil
|
return result.ID, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else return the first result if nothing is found
|
// Else return the first result if nothing is found
|
||||||
return searchResults[0].ID, nil
|
return searchResults[0].ID, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,16 @@ func (db *DbClient) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DbClient) TotalSongs() (int, error) {
|
||||||
|
existingSongsCollection := db.client.Database("song-recognition").Collection("existing-songs")
|
||||||
|
total, err := existingSongsCollection.CountDocuments(context.Background(), bson.D{})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(total), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DbClient) SongExists(key string) (bool, error) {
|
func (db *DbClient) SongExists(key string) (bool, error) {
|
||||||
existingSongsCollection := db.client.Database("song-recognition").Collection("existing-songs")
|
existingSongsCollection := db.client.Database("song-recognition").Collection("existing-songs")
|
||||||
filter := bson.M{"_id": key}
|
filter := bson.M{"_id": key}
|
||||||
|
|
@ -59,7 +69,7 @@ func (db *DbClient) RegisterSong(key string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DbClient) InsertChunkData(chunkfgp int64, chunkData interface{}) error {
|
func (db *DbClient) InsertChunkTag(chunkfgp int64, chunkTag interface{}) error {
|
||||||
chunksCollection := db.client.Database("song-recognition").Collection("chunks")
|
chunksCollection := db.client.Database("song-recognition").Collection("chunks")
|
||||||
|
|
||||||
filter := bson.M{"fingerprint": chunkfgp}
|
filter := bson.M{"fingerprint": chunkfgp}
|
||||||
|
|
@ -67,9 +77,9 @@ func (db *DbClient) InsertChunkData(chunkfgp int64, chunkData interface{}) error
|
||||||
var result bson.M
|
var result bson.M
|
||||||
err := chunksCollection.FindOne(context.Background(), filter).Decode(&result)
|
err := chunksCollection.FindOne(context.Background(), filter).Decode(&result)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// If the fingerprint already exists, append the chunkData to the existing list
|
// If the fingerprint already exists, append the chunkTag to the existing list
|
||||||
// fmt.Println("DUPLICATE FINGERPRINT: ", chunkfgp)
|
// fmt.Println("DUPLICATE FINGERPRINT: ", chunkfgp)
|
||||||
update := bson.M{"$push": bson.M{"chunkData": chunkData}}
|
update := bson.M{"$push": bson.M{"chunkTags": chunkTag}}
|
||||||
_, err := chunksCollection.UpdateOne(context.Background(), filter, update)
|
_, err := chunksCollection.UpdateOne(context.Background(), filter, update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error updating chunk data: %v", err)
|
return fmt.Errorf("error updating chunk data: %v", err)
|
||||||
|
|
@ -80,7 +90,7 @@ func (db *DbClient) InsertChunkData(chunkfgp int64, chunkData interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the document doesn't exist, insert a new document
|
// If the document doesn't exist, insert a new document
|
||||||
_, err = chunksCollection.InsertOne(context.Background(), bson.M{"fingerprint": chunkfgp, "chunkData": []interface{}{chunkData}})
|
_, err = chunksCollection.InsertOne(context.Background(), bson.M{"fingerprint": chunkfgp, "chunkTags": []interface{}{chunkTag}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error inserting chunk data: %v", err)
|
return fmt.Errorf("error inserting chunk data: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -88,16 +98,7 @@ func (db *DbClient) InsertChunkData(chunkfgp int64, chunkData interface{}) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type chunkData struct {
|
func (db *DbClient) GetChunkTags(chunkfgp int64) ([]primitive.M, error) {
|
||||||
SongName string `bson:"songName"`
|
|
||||||
SongArtist string `bson:"songArtist"`
|
|
||||||
BitDepth int `bson:"bitDepth"`
|
|
||||||
Channels int `bson:"channels"`
|
|
||||||
SamplingRate int `bson:"samplingRate"`
|
|
||||||
TimeStamp string `bson:"timeStamp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *DbClient) GetChunkData(chunkfgp int64) ([]primitive.M, error) {
|
|
||||||
chunksCollection := db.client.Database("song-recognition").Collection("chunks")
|
chunksCollection := db.client.Database("song-recognition").Collection("chunks")
|
||||||
|
|
||||||
filter := bson.M{"fingerprint": chunkfgp}
|
filter := bson.M{"fingerprint": chunkfgp}
|
||||||
|
|
@ -111,10 +112,45 @@ func (db *DbClient) GetChunkData(chunkfgp int64) ([]primitive.M, error) {
|
||||||
return nil, fmt.Errorf("error retrieving chunk data: %w", err)
|
return nil, fmt.Errorf("error retrieving chunk data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var listOfChunkData []primitive.M
|
var listOfChunkTags []primitive.M
|
||||||
for _, data := range result["chunkData"].(primitive.A) {
|
for _, data := range result["chunkTags"].(primitive.A) {
|
||||||
listOfChunkData = append(listOfChunkData, data.(primitive.M))
|
listOfChunkTags = append(listOfChunkTags, data.(primitive.M))
|
||||||
}
|
}
|
||||||
|
|
||||||
return listOfChunkData, nil
|
return listOfChunkTags, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DbClient) GetChunkTagForSong(songTitle, songArtist string) (bson.M, error) {
|
||||||
|
chunksCollection := db.client.Database("song-recognition").Collection("chunks")
|
||||||
|
|
||||||
|
filter := bson.M{
|
||||||
|
"chunkTags": bson.M{
|
||||||
|
"$elemMatch": bson.M{
|
||||||
|
"songtitle": songTitle,
|
||||||
|
"songartist": songArtist,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var result bson.M
|
||||||
|
if err := chunksCollection.FindOne(context.Background(), filter).Decode(&result); err != nil {
|
||||||
|
if err == mongo.ErrNoDocuments {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("error finding chunk: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var chunkTag map[string]interface{}
|
||||||
|
for _, chunk := range result["chunkTags"].(primitive.A) {
|
||||||
|
chunkMap, ok := chunk.(primitive.M)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if chunkMap["songtitle"] == songTitle && chunkMap["songartist"] == songArtist {
|
||||||
|
chunkTag = chunkMap
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunkTag, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue