diff --git a/chrome-plugin-test/background.js b/chrome-plugin-test/background.js
index 394d2b9..b04f2ce 100644
--- a/chrome-plugin-test/background.js
+++ b/chrome-plugin-test/background.js
@@ -1,3 +1,45 @@
chrome.action.onClicked.addListener((tab) => {
chrome.tabs.sendMessage(tab.id, {action: "togglePlayer"});
+});
+
+chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
+ if (request.action === "sendAudio") {
+ fetch('https://app102.acapp.acwing.com.cn/api/uploadAudio', {
+ method: 'POST',
+ body: request.formData
+ })
+ .then(response => response.json())
+ .then(data => {
+ sendResponse({success: true, data: data});
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ sendResponse({success: false, error: error.message});
+ });
+ return true; // 保持消息通道开放
+ }
+
+ if (request.action === "addSong") {
+ fetch('https://app102.acapp.acwing.com.cn/api/add', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(request.data)
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ sendResponse({success: true, data: data});
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ sendResponse({success: false, error: error.message});
+ });
+ return true; // 保持消息通道开放
+ }
});
\ No newline at end of file
diff --git a/chrome-plugin-test/content.js b/chrome-plugin-test/content.js
index 72d96ec..3210a33 100644
--- a/chrome-plugin-test/content.js
+++ b/chrome-plugin-test/content.js
@@ -1,8 +1,12 @@
+// 在文件顶部添加这行代码来进行调试
+console.log('Content script loaded');
+
let playerVisible = false;
let player;
let mediaRecorder;
let audioChunks = [];
let recordingTimeout;
+let isRecording = false;
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "togglePlayer") {
@@ -16,7 +20,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
function createPlayer() {
player = document.createElement('div');
player.id = 'ease-music-player';
-
+
const targetUrl = "https://app102.acapp.acwing.com.cn";
player.innerHTML = `
@@ -38,66 +42,69 @@ function createPlayer() {
function togglePlayer() {
playerVisible = !playerVisible;
player.style.display = playerVisible ? 'block' : 'none';
-
+
// 移除这行代码,不再修改body的overflow
// document.body.style.overflowY = playerVisible ? 'hidden' : '';
}
function toggleRecording() {
const recordButton = document.getElementById('ease-music-record');
- if (mediaRecorder && mediaRecorder.state === 'recording') {
+ if (isRecording) {
stopRecording();
recordButton.textContent = '开始识别';
+ isRecording = false;
} else {
startRecording();
recordButton.textContent = '识别中...';
+ isRecording = true;
}
}
function startRecording() {
+ console.log('startRecording function called'); // 添加这行来调试
audioChunks = [];
-
+
// 创建一个新的 AudioContext,设置采样率为 16000Hz
const audioContext = new (window.AudioContext || window.webkitAudioContext)({
sampleRate: 16000
});
-
+
// 创建一个 MediaStreamDestination
const destination = audioContext.createMediaStreamDestination();
-
+
// 获取页面中所有的 audio 和 video 元素
const mediaElements = document.querySelectorAll('audio, video');
-
+
mediaElements.forEach(element => {
if (element.captureStream) {
// 捕获媒体元素的音频流
const stream = element.captureStream();
const source = audioContext.createMediaStreamSource(stream);
-
+
// 创建一个 ScriptProcessorNode 用于重采样
const bufferSize = 4096;
const scriptNode = audioContext.createScriptProcessor(bufferSize, 1, 1);
-
+
scriptNode.onaudioprocess = (audioProcessingEvent) => {
const inputBuffer = audioProcessingEvent.inputBuffer;
const outputBuffer = audioProcessingEvent.outputBuffer;
-
+
for (let channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
const inputData = inputBuffer.getChannelData(channel);
const outputData = outputBuffer.getChannelData(channel);
-
+
// 简单的线性插值重采样
for (let i = 0; i < outputBuffer.length; i++) {
const index = i * inputBuffer.sampleRate / 16000;
const indexFloor = Math.floor(index);
const indexCeil = Math.ceil(index);
const fraction = index - indexFloor;
-
+
outputData[i] = (1 - fraction) * inputData[indexFloor] + fraction * inputData[indexCeil];
}
}
};
-
+
source.connect(scriptNode);
scriptNode.connect(destination);
}
@@ -105,7 +112,7 @@ function startRecording() {
// 创建 MediaRecorder
mediaRecorder = new MediaRecorder(destination.stream);
-
+
mediaRecorder.ondataavailable = event => {
audioChunks.push(event.data);
};
@@ -118,15 +125,19 @@ function startRecording() {
};
mediaRecorder.start();
-
- console.log('实际采样率:', audioContext.sampleRate);
+
+ console.log('Recording started, actual sample rate:', audioContext.sampleRate);
}
function stopRecording() {
- if (mediaRecorder) {
+ console.log('stopRecording function called'); // 添加这行来调试
+ if (mediaRecorder && mediaRecorder.state === 'recording') {
mediaRecorder.stop();
clearTimeout(recordingTimeout);
mediaRecorder.stream.getTracks().forEach(track => track.stop());
+ console.log('Recording stopped');
+ } else {
+ console.log('No active recording to stop');
}
}
@@ -135,18 +146,18 @@ function convertToWav(webmBlob) {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const fileReader = new FileReader();
- fileReader.onload = function(event) {
+ fileReader.onload = function (event) {
const audioData = event.target.result;
- audioContext.decodeAudioData(audioData, function(buffer) {
+ audioContext.decodeAudioData(audioData, function (buffer) {
const wavBlob = audioBufferToWav(buffer);
resolve(wavBlob);
- }, function(e) {
+ }, function (e) {
reject('音频解码失败');
});
};
- fileReader.onerror = function(error) {
+ fileReader.onerror = function (error) {
reject('文件读取失败');
};
@@ -252,25 +263,40 @@ function sendAudioToServer(audioBlob) {
const formData = new FormData();
var timestamp = Date.parse(new Date());
formData.append('audio', audioBlob, timestamp + '.wav');
-
+
fetch('https://app102.acapp.acwing.com.cn/api/uploadAudio', {
- // fetch('http://localhost:8809/api/uploadAudio', {
method: 'POST',
+ mode: 'cors',
+ credentials: 'include',
+ headers: {
+ 'Origin': 'chrome-extension://' + chrome.runtime.id
+ },
body: formData
})
- .then(response => response.json())
+ .then(response => {
+ console.log('Response status:', response.status);
+ console.log('Response headers:', response.headers);
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
.then(data => {
console.log('服务器响应:', data);
- if (data.code === "0" && data.data && Array.isArray(data.data)) {
- displaySongList(data.data);
+ if (data.artist && data.title) {
+ displaySongResult(data);
} else {
console.error('未能识别到歌曲');
}
})
- .catch(error => console.error('上传错误:', error));
+ .catch(error => {
+ console.error('上传错误:', error);
+ console.error('Error stack:', error.stack);
+ // 在这里添加错误处理逻辑,比如显示一个错误消息给用户
+ });
}
-function displaySongList(songs) {
+function displaySongResult(song) {
const resultDiv = document.createElement('div');
resultDiv.id = 'song-recognition-result';
resultDiv.style.cssText = `
@@ -282,44 +308,36 @@ function displaySongList(songs) {
padding: 15px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
- max-height: 60vh;
width: 300px;
- overflow-y: auto;
z-index: 10001;
font-family: Arial, sans-serif;
font-size: 14px;
`;
let html = '
';
- html += '识别结果
';
-
+ html += '识别结果
';
+
+ html += `
+
+
+ ${song.title}
+ ${song.artist}
+
+
+
`;
+
const closeButton = document.createElement('button');
closeButton.id = 'close-result';
closeButton.textContent = '关闭';
@@ -337,7 +355,7 @@ function displaySongList(songs) {
border-radius: 4px;
transition: background-color 0.3s;
`;
-
+
resultDiv.innerHTML = html;
resultDiv.appendChild(closeButton);
document.body.appendChild(resultDiv);
@@ -354,19 +372,15 @@ function displaySongList(songs) {
document.body.removeChild(resultDiv);
});
- // 为每个"添加"按钮添加点击事件
- resultDiv.querySelectorAll('.add-song-info').forEach(button => {
- button.addEventListener('click', function() {
- const index = this.getAttribute('data-index');
- const song = displaySongs[index];
- sendSongInfo(song.song, song.singer);
-
- // 点击后变灰并禁用
- this.style.backgroundColor = '#cccccc';
- this.style.cursor = 'default';
- this.disabled = true;
- this.textContent = '已添加';
- });
+ // 为"添加"按钮添加点击事件
+ document.getElementById('add-song-info').addEventListener('click', function () {
+ sendSongInfo(song.title, song.artist);
+
+ // 点击后变灰并禁用
+ this.style.backgroundColor = '#cccccc';
+ this.style.cursor = 'default';
+ this.disabled = true;
+ this.textContent = '已添加';
});
makeDraggable(resultDiv, document.getElementById('result-header'));
@@ -374,17 +388,16 @@ function displaySongList(songs) {
function sendSongInfo(songName, singerName) {
console.log(`添加歌曲信息:${songName} - ${singerName}`);
- // fetch('http://localhost:8809/api/add', {
- fetch('https://app102.acapp.acwing.com.cn/api/add', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ title: songName, artist: singerName }),
- })
- .then(response => response.json())
- .then(data => console.log('API response:', data))
- .catch(error => console.error('Error:', error));
+ chrome.runtime.sendMessage({
+ action: "addSong",
+ data: { title: songName, artist: singerName }
+ }, response => {
+ if (response.success) {
+ console.log('API response:', response.data);
+ } else {
+ console.error('Error:', response.error);
+ }
+ });
}
function makeDraggable(element, dragHandle) {
diff --git a/chrome-plugin-test/manifest.json b/chrome-plugin-test/manifest.json
index 82db1fd..9baee69 100644
--- a/chrome-plugin-test/manifest.json
+++ b/chrome-plugin-test/manifest.json
@@ -3,7 +3,13 @@
"name": "EaseMusic",
"version": "1.0",
"description": "一个简单的音乐播放Chrome插件",
- "permissions": ["activeTab"],
+ "permissions": [
+ "activeTab",
+ "https://app102.acapp.acwing.com.cn/*"
+ ],
+ "host_permissions": [
+ "https://app102.acapp.acwing.com.cn/*"
+ ],
"action": {
"default_icon": {
"16": "icon16.png",
diff --git a/musicBackend/pom.xml b/musicBackend/pom.xml
index e757b1a..286e760 100644
--- a/musicBackend/pom.xml
+++ b/musicBackend/pom.xml
@@ -98,6 +98,12 @@
org.springframework.boot
spring-boot-starter-aop
+
+
+ com.acrcloud.sdks
+ com.acrcloud.sdks.recognizer
+ 1.0.4
+
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/Test.java b/musicBackend/src/main/java/com/cph/musicbackend/Test.java
new file mode 100644
index 0000000..c69558c
--- /dev/null
+++ b/musicBackend/src/main/java/com/cph/musicbackend/Test.java
@@ -0,0 +1,58 @@
+package com.cph.musicbackend;
+
+import java.io.*;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.acrcloud.utils.ACRCloudRecognizer;
+
+public class Test {
+
+ public static void main(String[] args) {
+ Map config = new HashMap();
+
+ config.put("host", "identify-cn-north-1.acrcloud.cn");
+ config.put("access_key", "3076056eb203a361d9341411191e1e25");
+ config.put("access_secret", "TRlwfLkzv8orvm7gIePYvaM8wJvLWMJBBTrJujvQ");
+
+ config.put("debug", false);
+ config.put("timeout", 10); // seconds
+
+ ACRCloudRecognizer re = new ACRCloudRecognizer(config);
+
+ // It will skip 80 seconds.
+ String filename = "D:\\audio\\1.mp3";
+ String result = re.recognizeByFile(filename, 1);
+ System.out.println(result);
+
+ File file = new File(filename);
+ byte[] buffer = new byte[3 * 1024 * 1024];
+ if (!file.exists()) {
+ return;
+ }
+ FileInputStream fin = null;
+ int bufferLen = 0;
+ try {
+ fin = new FileInputStream(file);
+ bufferLen = fin.read(buffer, 0, buffer.length);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (fin != null) {
+ fin.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ System.out.println("bufferLen=" + bufferLen);
+
+ if (bufferLen <= 0)
+ return;
+
+ // It will skip 80 seconds from the begginning of (buffer).
+ result = re.recognizeByFileBuffer(buffer, bufferLen, 1);
+ System.out.println(result);
+ }
+}
\ No newline at end of file
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/config/ACRCloudRecognizerConfig.java b/musicBackend/src/main/java/com/cph/musicbackend/config/ACRCloudRecognizerConfig.java
new file mode 100644
index 0000000..1f0d3b4
--- /dev/null
+++ b/musicBackend/src/main/java/com/cph/musicbackend/config/ACRCloudRecognizerConfig.java
@@ -0,0 +1,26 @@
+package com.cph.musicbackend.config;
+
+import com.acrcloud.utils.ACRCloudRecognizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class ACRCloudRecognizerConfig {
+ @Bean
+ public ACRCloudRecognizer acrCloudRecognizer()
+ {
+ Map config = new HashMap();
+
+ config.put("host", "identify-cn-north-1.acrcloud.cn");
+ config.put("access_key", "3076056eb203a361d9341411191e1e25");
+ config.put("access_secret", "TRlwfLkzv8orvm7gIePYvaM8wJvLWMJBBTrJujvQ");
+
+ config.put("debug", false);
+ config.put("timeout", 10); // seconds
+
+ return new ACRCloudRecognizer(config);
+ }
+}
\ No newline at end of file
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/controller/MusicController.java b/musicBackend/src/main/java/com/cph/musicbackend/controller/MusicController.java
index b8e787a..a0ef282 100644
--- a/musicBackend/src/main/java/com/cph/musicbackend/controller/MusicController.java
+++ b/musicBackend/src/main/java/com/cph/musicbackend/controller/MusicController.java
@@ -8,7 +8,8 @@
import com.cph.musicbackend.entity.User;
import com.cph.musicbackend.mapper.MusicMapper;
import com.cph.musicbackend.mapper.UserMapper;
-import com.cph.musicbackend.rd3.MusicRecUtil;
+import com.cph.musicbackend.rd3.AcrCloudUtil;
+import com.cph.musicbackend.rd3.xunfei.MusicRecUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
@@ -17,13 +18,11 @@
import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@RestController
-@CrossOrigin
public class MusicController {
@@ -36,6 +35,9 @@ public class MusicController {
@Autowired
UserMapper userMapper;
+ @Autowired
+ AcrCloudUtil acrCloudUtil;
+
@GetMapping("/api/musicList")
@RecognizeAddress
public List getMusciList() {
@@ -114,7 +116,8 @@ public Object recongnizeMusic(@RequestParam("audio") MultipartFile file) {
// 保存文件
File destFile = new File(dir.getAbsolutePath() + File.separator + fileName);
file.transferTo(destFile);
- return MusicRecUtil.recongnizeFile(dir.getAbsolutePath() + File.separator + fileName);
+ return acrCloudUtil.recongizeByFile(dir.getAbsolutePath() + File.separator + fileName);
+// return MusicRecUtil.recongnizeFile(dir.getAbsolutePath() + File.separator + fileName);
} catch (IOException e) {
return "{\"error\": \"" + e.getMessage() + "\"}";
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/rd3/AcrCloudUtil.java b/musicBackend/src/main/java/com/cph/musicbackend/rd3/AcrCloudUtil.java
new file mode 100644
index 0000000..b97b690
--- /dev/null
+++ b/musicBackend/src/main/java/com/cph/musicbackend/rd3/AcrCloudUtil.java
@@ -0,0 +1,48 @@
+package com.cph.musicbackend.rd3;
+
+import com.acrcloud.utils.ACRCloudRecognizer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class AcrCloudUtil {
+ @Autowired
+ public ACRCloudRecognizer re;
+
+ public Map recongizeByFile(String filename) {
+ HashMap resultMap = new HashMap<>();
+ String result = re.recognizeByFile(filename, 1);
+ // 使用示例结果进行解析
+// String result = "{\"status\":{\"msg\":\"Success\",\"version\":\"1.0\",\"code\":0},\"metadata\":{\"timestamp_utc\":\"2024-10-08 12:08:34\",\"music\":[{\"lan\":\"国语\",\"duration_ms\":200000,\"external_ids\":{},\"db_begin_time_offset_ms\":4080,\"artists\":[{\"name\":\"周杰伦\"}],\"db_end_time_offset_ms\":14600,\"sample_begin_time_offset_ms\":0,\"sample_end_time_offset_ms\":10520,\"play_offset_ms\":15540,\"result_from\":3,\"title\":\"前世情人\",\"label\":\"JVR\",\"score\":100,\"acrid\":\"e3c887cf408db8991a68a843f1afd5a0\",\"language\":\"zh\",\"external_metadata\":{},\"release_date\":\"2016-06-24\",\"album\":{\"name\":\"周杰伦的床边故事\"}},{\"duration_ms\":200460,\"external_ids\":{},\"db_begin_time_offset_ms\":4060,\"artists\":[{\"name\":\"周杰伦\"}],\"label\":\"杰威尔音乐有限公司\",\"db_end_time_offset_ms\":14500,\"sample_begin_time_offset_ms\":0,\"sample_end_time_offset_ms\":10440,\"play_offset_ms\":15520,\"result_from\":3,\"title\":\"前世情人\",\"score\":100,\"language\":\"zh\",\"acrid\":\"0eb1c19384ec445e15c6cb3c11c706ba\",\"release_date\":\"2016-06-24\",\"external_metadata\":{},\"album\":{\"name\":\"周杰伦的床边故事\"}}]},\"result_type\":0,\"cost_time\":0.029999971389771}";
+ System.out.println(result);
+
+ try {
+ JsonObject jsonObject = JsonParser.parseString(result).getAsJsonObject();
+ JsonObject metadata = jsonObject.getAsJsonObject("metadata");
+ JsonElement musicElement = metadata.get("music");
+
+ if (musicElement != null && musicElement.isJsonArray() && musicElement.getAsJsonArray().size() > 0) {
+ JsonObject musicObject = musicElement.getAsJsonArray().get(0).getAsJsonObject();
+
+ String title = musicObject.get("title").getAsString();
+ String artist = musicObject.getAsJsonArray("artists").get(0).getAsJsonObject().get("name").getAsString();
+
+ resultMap.put("title", title);
+ resultMap.put("artist", artist);
+ }
+ } catch (Exception e) {
+ System.err.println("解析结果时发生错误: " + e.getMessage());
+ }
+
+ return resultMap;
+ }
+}
\ No newline at end of file
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/rd3/FileUtil.java b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/FileUtil.java
similarity index 97%
rename from musicBackend/src/main/java/com/cph/musicbackend/rd3/FileUtil.java
rename to musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/FileUtil.java
index b3acbbd..c316045 100644
--- a/musicBackend/src/main/java/com/cph/musicbackend/rd3/FileUtil.java
+++ b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/FileUtil.java
@@ -1,4 +1,4 @@
-package com.cph.musicbackend.rd3;
+package com.cph.musicbackend.rd3.xunfei;
import java.io.*;
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/rd3/HttpUtil.java b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/HttpUtil.java
similarity index 97%
rename from musicBackend/src/main/java/com/cph/musicbackend/rd3/HttpUtil.java
rename to musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/HttpUtil.java
index 966837a..476b247 100644
--- a/musicBackend/src/main/java/com/cph/musicbackend/rd3/HttpUtil.java
+++ b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/HttpUtil.java
@@ -1,4 +1,4 @@
-package com.cph.musicbackend.rd3;
+package com.cph.musicbackend.rd3.xunfei;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
diff --git a/musicBackend/src/main/java/com/cph/musicbackend/rd3/MusicRecUtil.java b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/MusicRecUtil.java
similarity index 99%
rename from musicBackend/src/main/java/com/cph/musicbackend/rd3/MusicRecUtil.java
rename to musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/MusicRecUtil.java
index 27ceb06..900684a 100644
--- a/musicBackend/src/main/java/com/cph/musicbackend/rd3/MusicRecUtil.java
+++ b/musicBackend/src/main/java/com/cph/musicbackend/rd3/xunfei/MusicRecUtil.java
@@ -1,4 +1,4 @@
-package com.cph.musicbackend.rd3;
+package com.cph.musicbackend.rd3.xunfei;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
diff --git a/src/utils/api.js b/src/utils/api.js
index de6fa14..0df6ee1 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -1,7 +1,9 @@
import axios from 'axios';
export const instance = axios.create({
- baseURL: 'https://app102.acapp.acwing.com.cn/api',
+ // baseURL: 'https://app102.acapp.acwing.com.cn/api',
+ baseURL: 'http://localhost:8809/api',
+
headers: {
'Content-Type': 'application/json',
}