feat: Add new dependencies and SunoApi class for audio generation
functionality Added new dependencies for axios, pino, and user-agents in the package.json and pnpm-lock.yaml files to support audio generation functionality. Additionally, implemented a new SunoApi class in the lib directory to handle the audio generation process, including functions for generating, customizing, and retrieving audio content from the Suno.ai API. This addresses the need for enhanced audio processing capabilities and lays the groundwork for efficient integration with the Suno.ai API. No issues are associated with these additions.
This commit is contained in:
parent
12f31cb3ea
commit
0fcf77df6d
@ -15,14 +15,18 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.8",
|
||||
"next": "14.1.4",
|
||||
"pino": "^8.19.0",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
"react-dom": "^18",
|
||||
"user-agents": "^1.1.156"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"@types/user-agents": "^1.0.4",
|
||||
"autoprefixer": "^10.0.1",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.1.4",
|
||||
|
223
pnpm-lock.yaml
223
pnpm-lock.yaml
@ -5,15 +5,24 @@ settings:
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
axios:
|
||||
specifier: ^1.6.8
|
||||
version: 1.6.8
|
||||
next:
|
||||
specifier: 14.1.4
|
||||
version: 14.1.4(react-dom@18.2.0)(react@18.2.0)
|
||||
pino:
|
||||
specifier: ^8.19.0
|
||||
version: 8.19.0
|
||||
react:
|
||||
specifier: ^18
|
||||
version: 18.2.0
|
||||
react-dom:
|
||||
specifier: ^18
|
||||
version: 18.2.0(react@18.2.0)
|
||||
user-agents:
|
||||
specifier: ^1.1.156
|
||||
version: 1.1.156
|
||||
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
@ -25,6 +34,9 @@ devDependencies:
|
||||
'@types/react-dom':
|
||||
specifier: ^18
|
||||
version: 18.2.22
|
||||
'@types/user-agents':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4
|
||||
autoprefixer:
|
||||
specifier: ^10.0.1
|
||||
version: 10.4.19(postcss@8.4.38)
|
||||
@ -322,6 +334,10 @@ packages:
|
||||
csstype: 3.1.3
|
||||
dev: true
|
||||
|
||||
/@types/user-agents@1.0.4:
|
||||
resolution: {integrity: sha512-AjeFc4oX5WPPflgKfRWWJfkEk7Wu82fnj1rROPsiqFt6yElpdGFg8Srtm/4PU4rA9UiDUZlruGPgcwTMQlwq4w==, tarball: https://registry.npmmirror.com/@types/user-agents/-/user-agents-1.0.4.tgz}
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.3):
|
||||
resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-6.21.0.tgz}
|
||||
engines: {node: ^16.0.0 || >=18.0.0}
|
||||
@ -390,6 +406,13 @@ packages:
|
||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==, tarball: https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz}
|
||||
dev: true
|
||||
|
||||
/abort-controller@3.0.0:
|
||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==, tarball: https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz}
|
||||
engines: {node: '>=6.5'}
|
||||
dependencies:
|
||||
event-target-shim: 5.0.1
|
||||
dev: false
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.11.3):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, tarball: https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz}
|
||||
peerDependencies:
|
||||
@ -567,6 +590,15 @@ packages:
|
||||
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==, tarball: https://registry.npmmirror.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz}
|
||||
dev: true
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, tarball: https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz}
|
||||
dev: false
|
||||
|
||||
/atomic-sleep@1.0.0:
|
||||
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==, tarball: https://registry.npmmirror.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz}
|
||||
engines: {node: '>=8.0.0'}
|
||||
dev: false
|
||||
|
||||
/autoprefixer@10.4.19(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==, tarball: https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.19.tgz}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@ -595,6 +627,16 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/axios@1.6.8:
|
||||
resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==, tarball: https://registry.npmmirror.com/axios/-/axios-1.6.8.tgz}
|
||||
dependencies:
|
||||
follow-redirects: 1.15.6
|
||||
form-data: 4.0.0
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/axobject-query@3.2.1:
|
||||
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==, tarball: https://registry.npmmirror.com/axobject-query/-/axobject-query-3.2.1.tgz}
|
||||
dependencies:
|
||||
@ -605,6 +647,10 @@ packages:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, tarball: https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz}
|
||||
dev: true
|
||||
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, tarball: https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz}
|
||||
dev: false
|
||||
|
||||
/binary-extensions@2.3.0:
|
||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, tarball: https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz}
|
||||
engines: {node: '>=8'}
|
||||
@ -641,6 +687,13 @@ packages:
|
||||
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
||||
dev: true
|
||||
|
||||
/buffer@6.0.3:
|
||||
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==, tarball: https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz}
|
||||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
ieee754: 1.2.1
|
||||
dev: false
|
||||
|
||||
/busboy@1.6.0:
|
||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==, tarball: https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz}
|
||||
engines: {node: '>=10.16.0'}
|
||||
@ -710,6 +763,13 @@ packages:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz}
|
||||
dev: true
|
||||
|
||||
/combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, tarball: https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: false
|
||||
|
||||
/commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==, tarball: https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz}
|
||||
engines: {node: '>= 6'}
|
||||
@ -814,6 +874,11 @@ packages:
|
||||
object-keys: 1.1.1
|
||||
dev: true
|
||||
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, tarball: https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, tarball: https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz}
|
||||
engines: {node: '>=6'}
|
||||
@ -1274,6 +1339,16 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/event-target-shim@5.0.1:
|
||||
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==, tarball: https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/events@3.3.0:
|
||||
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, tarball: https://registry.npmmirror.com/events/-/events-3.3.0.tgz}
|
||||
engines: {node: '>=0.8.x'}
|
||||
dev: false
|
||||
|
||||
/fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, tarball: https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz}
|
||||
dev: true
|
||||
@ -1297,6 +1372,11 @@ packages:
|
||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, tarball: https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz}
|
||||
dev: true
|
||||
|
||||
/fast-redact@3.5.0:
|
||||
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==, tarball: https://registry.npmmirror.com/fast-redact/-/fast-redact-3.5.0.tgz}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/fastq@1.17.1:
|
||||
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==, tarball: https://registry.npmmirror.com/fastq/-/fastq-1.17.1.tgz}
|
||||
dependencies:
|
||||
@ -1338,6 +1418,16 @@ packages:
|
||||
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==, tarball: https://registry.npmmirror.com/flatted/-/flatted-3.3.1.tgz}
|
||||
dev: true
|
||||
|
||||
/follow-redirects@1.15.6:
|
||||
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==, tarball: https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/for-each@0.3.3:
|
||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==, tarball: https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz}
|
||||
dependencies:
|
||||
@ -1352,6 +1442,15 @@ packages:
|
||||
signal-exit: 4.1.0
|
||||
dev: true
|
||||
|
||||
/form-data@4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==, tarball: https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/fraction.js@4.3.7:
|
||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==, tarball: https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz}
|
||||
dev: true
|
||||
@ -1527,6 +1626,10 @@ packages:
|
||||
function-bind: 1.1.2
|
||||
dev: true
|
||||
|
||||
/ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, tarball: https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz}
|
||||
dev: false
|
||||
|
||||
/ignore@5.3.1:
|
||||
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==, tarball: https://registry.npmmirror.com/ignore/-/ignore-5.3.1.tgz}
|
||||
engines: {node: '>= 4'}
|
||||
@ -1860,6 +1963,10 @@ packages:
|
||||
p-locate: 5.0.0
|
||||
dev: true
|
||||
|
||||
/lodash.clonedeep@4.5.0:
|
||||
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==, tarball: https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz}
|
||||
dev: false
|
||||
|
||||
/lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, tarball: https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz}
|
||||
dev: true
|
||||
@ -1895,6 +2002,18 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, tarball: https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, tarball: https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz}
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
dev: false
|
||||
|
||||
/minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, tarball: https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz}
|
||||
dependencies:
|
||||
@ -2070,6 +2189,11 @@ packages:
|
||||
es-object-atoms: 1.0.0
|
||||
dev: true
|
||||
|
||||
/on-exit-leak-free@2.1.2:
|
||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==, tarball: https://registry.npmmirror.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, tarball: https://registry.npmmirror.com/once/-/once-1.4.0.tgz}
|
||||
dependencies:
|
||||
@ -2154,6 +2278,34 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/pino-abstract-transport@1.1.0:
|
||||
resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==, tarball: https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz}
|
||||
dependencies:
|
||||
readable-stream: 4.5.2
|
||||
split2: 4.2.0
|
||||
dev: false
|
||||
|
||||
/pino-std-serializers@6.2.2:
|
||||
resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==, tarball: https://registry.npmmirror.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz}
|
||||
dev: false
|
||||
|
||||
/pino@8.19.0:
|
||||
resolution: {integrity: sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==, tarball: https://registry.npmmirror.com/pino/-/pino-8.19.0.tgz}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
fast-redact: 3.5.0
|
||||
on-exit-leak-free: 2.1.2
|
||||
pino-abstract-transport: 1.1.0
|
||||
pino-std-serializers: 6.2.2
|
||||
process-warning: 3.0.0
|
||||
quick-format-unescaped: 4.0.4
|
||||
real-require: 0.2.0
|
||||
safe-stable-stringify: 2.4.3
|
||||
sonic-boom: 3.8.0
|
||||
thread-stream: 2.4.1
|
||||
dev: false
|
||||
|
||||
/pirates@4.0.6:
|
||||
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==, tarball: https://registry.npmmirror.com/pirates/-/pirates-4.0.6.tgz}
|
||||
engines: {node: '>= 6'}
|
||||
@ -2248,6 +2400,15 @@ packages:
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dev: true
|
||||
|
||||
/process-warning@3.0.0:
|
||||
resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==, tarball: https://registry.npmmirror.com/process-warning/-/process-warning-3.0.0.tgz}
|
||||
dev: false
|
||||
|
||||
/process@0.11.10:
|
||||
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==, tarball: https://registry.npmmirror.com/process/-/process-0.11.10.tgz}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
dev: false
|
||||
|
||||
/prop-types@15.8.1:
|
||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, tarball: https://registry.npmmirror.com/prop-types/-/prop-types-15.8.1.tgz}
|
||||
dependencies:
|
||||
@ -2256,6 +2417,10 @@ packages:
|
||||
react-is: 16.13.1
|
||||
dev: true
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, tarball: https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz}
|
||||
dev: false
|
||||
|
||||
/punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, tarball: https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz}
|
||||
engines: {node: '>=6'}
|
||||
@ -2265,6 +2430,10 @@ packages:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz}
|
||||
dev: true
|
||||
|
||||
/quick-format-unescaped@4.0.4:
|
||||
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==, tarball: https://registry.npmmirror.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz}
|
||||
dev: false
|
||||
|
||||
/react-dom@18.2.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==, tarball: https://registry.npmmirror.com/react-dom/-/react-dom-18.2.0.tgz}
|
||||
peerDependencies:
|
||||
@ -2292,6 +2461,17 @@ packages:
|
||||
pify: 2.3.0
|
||||
dev: true
|
||||
|
||||
/readable-stream@4.5.2:
|
||||
resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==, tarball: https://registry.npmmirror.com/readable-stream/-/readable-stream-4.5.2.tgz}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
abort-controller: 3.0.0
|
||||
buffer: 6.0.3
|
||||
events: 3.3.0
|
||||
process: 0.11.10
|
||||
string_decoder: 1.3.0
|
||||
dev: false
|
||||
|
||||
/readdirp@3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, tarball: https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz}
|
||||
engines: {node: '>=8.10.0'}
|
||||
@ -2299,6 +2479,11 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/real-require@0.2.0:
|
||||
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==, tarball: https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
dev: false
|
||||
|
||||
/reflect.getprototypeof@1.0.6:
|
||||
resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==, tarball: https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2381,6 +2566,10 @@ packages:
|
||||
isarray: 2.0.5
|
||||
dev: true
|
||||
|
||||
/safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, tarball: https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz}
|
||||
dev: false
|
||||
|
||||
/safe-regex-test@1.0.3:
|
||||
resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==, tarball: https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2390,6 +2579,11 @@ packages:
|
||||
is-regex: 1.1.4
|
||||
dev: true
|
||||
|
||||
/safe-stable-stringify@2.4.3:
|
||||
resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==, tarball: https://registry.npmmirror.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/scheduler@0.23.0:
|
||||
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==, tarball: https://registry.npmmirror.com/scheduler/-/scheduler-0.23.0.tgz}
|
||||
dependencies:
|
||||
@ -2463,10 +2657,21 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/sonic-boom@3.8.0:
|
||||
resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==, tarball: https://registry.npmmirror.com/sonic-boom/-/sonic-boom-3.8.0.tgz}
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
dev: false
|
||||
|
||||
/source-map-js@1.2.0:
|
||||
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==, tarball: https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/split2@4.2.0:
|
||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, tarball: https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz}
|
||||
engines: {node: '>= 10.x'}
|
||||
dev: false
|
||||
|
||||
/streamsearch@1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==, tarball: https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@ -2535,6 +2740,12 @@ packages:
|
||||
es-object-atoms: 1.0.0
|
||||
dev: true
|
||||
|
||||
/string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, tarball: https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz}
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, tarball: https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz}
|
||||
engines: {node: '>=8'}
|
||||
@ -2655,6 +2866,12 @@ packages:
|
||||
any-promise: 1.3.0
|
||||
dev: true
|
||||
|
||||
/thread-stream@2.4.1:
|
||||
resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==, tarball: https://registry.npmmirror.com/thread-stream/-/thread-stream-2.4.1.tgz}
|
||||
dependencies:
|
||||
real-require: 0.2.0
|
||||
dev: false
|
||||
|
||||
/to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, tarball: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz}
|
||||
engines: {node: '>=8.0'}
|
||||
@ -2780,6 +2997,12 @@ packages:
|
||||
punycode: 2.3.1
|
||||
dev: true
|
||||
|
||||
/user-agents@1.1.156:
|
||||
resolution: {integrity: sha512-gphkDF41zQ/JGHc4hv2n05/okucmb7qYlhN2BKur0IKd1pkgXhS6l1GILoMQ/Hak7Z5FP3+X+0h7QcGF/pgxXw==, tarball: https://registry.npmmirror.com/user-agents/-/user-agents-1.1.156.tgz}
|
||||
dependencies:
|
||||
lodash.clonedeep: 4.5.0
|
||||
dev: false
|
||||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, tarball: https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz}
|
||||
dev: true
|
||||
|
50
src/app/api/custom_generate/route.ts
Normal file
50
src/app/api/custom_generate/route.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import SunoApi from '@/lib/sunoApi';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
if (req.method === 'POST') {
|
||||
try {
|
||||
const body = await req.json();
|
||||
const { prompt, tags, title, make_instrumental, wait_audio } = body;
|
||||
|
||||
// 校验输入参数
|
||||
if (!prompt || !tags || !title) {
|
||||
return new NextResponse(JSON.stringify({ error: 'Prompt, tags, and title are required' }), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// 调用 SunoApi.custom_generate 方法生成定制音频
|
||||
const audioInfo = await SunoApi.custom_generate(
|
||||
prompt, tags, title,
|
||||
make_instrumental == true,
|
||||
wait_audio == true
|
||||
);
|
||||
|
||||
// 使用 NextResponse 构建成功响应
|
||||
return new NextResponse(JSON.stringify(audioInfo), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Error generating custom audio:', error.response.data);
|
||||
if (error.response.status === 402) {
|
||||
return new NextResponse(JSON.stringify({ error: error.response.data.detail }), {
|
||||
status: 402,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
// 使用 NextResponse 构建错误响应
|
||||
return new NextResponse(JSON.stringify({ error: 'Internal server error' }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return new NextResponse('Method Not Allowed', {
|
||||
headers: { Allow: 'POST' },
|
||||
status: 405
|
||||
});
|
||||
}
|
||||
}
|
46
src/app/api/generate/route.ts
Normal file
46
src/app/api/generate/route.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import SunoApi from '@/lib/sunoApi';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
if (req.method === 'POST') {
|
||||
try {
|
||||
const body = await req.json();
|
||||
const { prompt, make_instrumental, wait_audio } = body;
|
||||
|
||||
// 校验输入参数
|
||||
if (!prompt) {
|
||||
return new NextResponse(JSON.stringify({ error: 'Prompt is required' }), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// 调用 SunoApi.generate 方法生成音频
|
||||
const audioInfo = await SunoApi.generate(prompt, make_instrumental == true, wait_audio == true);
|
||||
|
||||
// 使用 NextResponse 构建成功响应
|
||||
return new NextResponse(JSON.stringify(audioInfo), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error('Error generating custom audio:', JSON.stringify(error.response.data));
|
||||
if (error.response.status === 402) {
|
||||
return new NextResponse(JSON.stringify({ error: error.response.data.detail }), {
|
||||
status: 402,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
// 使用 NextResponse 构建错误响应
|
||||
return new NextResponse(JSON.stringify({ error: 'Internal server error: ' + JSON.stringify(error.response.data.detail) }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return new NextResponse('Method Not Allowed', {
|
||||
headers: { Allow: 'POST' },
|
||||
status: 405
|
||||
});
|
||||
}
|
||||
}
|
38
src/app/api/get/route.ts
Normal file
38
src/app/api/get/route.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import SunoApi from '@/lib/sunoApi';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
if (req.method === 'GET') {
|
||||
try {
|
||||
// 修复了获取查询参数的方式
|
||||
const url = new URL(req.url);
|
||||
const songIds = url.searchParams.get('ids');
|
||||
let audioInfo = [];
|
||||
if (songIds && songIds.length > 0) {
|
||||
const idsArray = songIds.split(',');
|
||||
// 调用 SunoApi.get 方法获取音频信息
|
||||
audioInfo = await SunoApi.get(idsArray);
|
||||
} else {
|
||||
audioInfo = await SunoApi.get();
|
||||
}
|
||||
|
||||
// 使用 NextResponse 构建成功响应
|
||||
return new NextResponse(JSON.stringify(audioInfo), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching audio:', error);
|
||||
// 使用 NextResponse 构建错误响应
|
||||
return new NextResponse(JSON.stringify({ error: 'Internal server error' }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return new NextResponse('Method Not Allowed', {
|
||||
headers: { Allow: 'GET' },
|
||||
status: 405
|
||||
});
|
||||
}
|
||||
}
|
29
src/app/api/get_limit/route.ts
Normal file
29
src/app/api/get_limit/route.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import SunoApi from '@/lib/sunoApi';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
if (req.method === 'GET') {
|
||||
try {
|
||||
// 调用 SunoApi.get_limit 方法获取剩余的信用额度
|
||||
const limit = await SunoApi.get_limit();
|
||||
|
||||
// 使用 NextResponse 构建成功响应
|
||||
return new NextResponse(JSON.stringify({ limit }), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching limit:', error);
|
||||
// 使用 NextResponse 构建错误响应
|
||||
return new NextResponse(JSON.stringify({ error: 'Internal server error' }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return new NextResponse('Method Not Allowed', {
|
||||
headers: { Allow: 'GET' },
|
||||
status: 405
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
import axios from 'axios';
|
||||
import UserAgent from 'user-agents';
|
||||
|
||||
|
||||
|
||||
interface AudioInfo {
|
||||
id: string;
|
||||
title?: string;
|
||||
image_url?: string;
|
||||
lyric?: string;
|
||||
audio_url?: string;
|
||||
video_url?: string;
|
||||
created_at: string;
|
||||
model_name: string;
|
||||
gpt_description_prompt?: string;
|
||||
prompt?: string;
|
||||
status: string;
|
||||
type?: string;
|
||||
tags?: string;
|
||||
duration?: string;
|
||||
}
|
||||
/**
|
||||
* 暂停指定的秒数。
|
||||
* @param x 最小秒数。
|
||||
* @param y 最大秒数(可选)。
|
||||
*/
|
||||
const sleep = (x: number, y?: number): Promise<void> => {
|
||||
let timeout = x * 1000;
|
||||
if (y !== undefined && y !== x) {
|
||||
const min = Math.min(x, y);
|
||||
const max = Math.max(x, y);
|
||||
timeout = Math.floor(Math.random() * (max - min + 1) + min) * 1000;
|
||||
}
|
||||
console.log(`Sleeping for ${timeout / 1000} seconds`);
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
||||
class SunoApi {
|
||||
private static baseUrl: string = 'https://studio-api.suno.ai';
|
||||
private static clerkBaseUrl: string = 'https://clerk.suno.ai';
|
||||
private static cookie: string = process.env.SUNO_COOKIE || '';
|
||||
private static userAgent: string = new UserAgent().toString();
|
||||
private static sid: string | null = null;
|
||||
|
||||
private static async getAuthToken(): Promise<string> {
|
||||
|
||||
// 获取会话ID的URL
|
||||
const getSessionUrl = `${SunoApi.clerkBaseUrl}/v1/client?_clerk_js_version=4.70.5`;
|
||||
// 交换令牌的URL模板
|
||||
const exchangeTokenUrlTemplate = `${SunoApi.clerkBaseUrl}/v1/client/sessions/{sid}/tokens/api?_clerk_js_version=4.70.0`;
|
||||
|
||||
// 获取会话ID
|
||||
const sessionResponse = await axios.get(getSessionUrl, {
|
||||
headers: {
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
'Cookie': SunoApi.cookie,
|
||||
},
|
||||
});
|
||||
const sid = sessionResponse.data.response?.last_active_session_id;
|
||||
if (!sid) {
|
||||
throw new Error("Failed to get session id");
|
||||
}
|
||||
console.log(`Successfully retrieved session ID: ${sid}`);
|
||||
SunoApi.sid = sid; // 保存会话ID以备后用
|
||||
|
||||
// 使用会话ID获取JWT令牌
|
||||
const exchangeTokenUrl = exchangeTokenUrlTemplate.replace('{sid}', sid);
|
||||
// console.log("Exchange Token URL:\n", exchangeTokenUrl);
|
||||
// console.log("Exchange User-Agent:\n", SunoApi.userAgent);
|
||||
// console.log("Exchange Cookie:\n", SunoApi.cookie);
|
||||
const tokenResponse = await axios.post(
|
||||
exchangeTokenUrl,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
'Cookie': SunoApi.cookie,
|
||||
},
|
||||
},
|
||||
);
|
||||
console.log("Token Response:\n", JSON.stringify(tokenResponse.data, null, 2));
|
||||
|
||||
return tokenResponse.data.jwt;
|
||||
}
|
||||
public static async KeepAlive(): Promise<void> {
|
||||
if (!SunoApi.sid) {
|
||||
throw new Error("Session ID is not set. Cannot renew token.");
|
||||
}
|
||||
// 续订会话令牌的URL
|
||||
const renewUrl = `${SunoApi.clerkBaseUrl}/v1/client/sessions/${SunoApi.sid}/tokens/api?_clerk_js_version=4.70.0`;
|
||||
// 续订会话令牌
|
||||
const renewResponse = await axios.post(
|
||||
renewUrl,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
'Cookie': SunoApi.cookie,
|
||||
},
|
||||
},
|
||||
);
|
||||
console.log("Renew Response:\n", JSON.stringify(renewResponse.data, null, 2));
|
||||
await sleep(1, 2);
|
||||
const newToken = renewResponse.data.jwt;
|
||||
// 更新请求头中的Authorization字段,使用新的JWT令牌
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
|
||||
}
|
||||
|
||||
public static async generate(
|
||||
prompt: string,
|
||||
make_instrumental: boolean = false,
|
||||
wait_audio: boolean = false,
|
||||
): Promise<AudioInfo[]> {
|
||||
|
||||
const audios = this.generateSongs(prompt, false, undefined, undefined, make_instrumental, wait_audio);
|
||||
console.log("Custom Generate Response:\n", JSON.stringify(audios, null, 2));
|
||||
return audios;
|
||||
}
|
||||
|
||||
public static async custom_generate(
|
||||
prompt: string,
|
||||
tags: string,
|
||||
title: string,
|
||||
make_instrumental: boolean = false,
|
||||
wait_audio: boolean = false,
|
||||
): Promise<AudioInfo[]> {
|
||||
|
||||
const audios = await this.generateSongs(prompt, true, tags, title, make_instrumental, wait_audio);
|
||||
console.log("Custom Generate Response:\n", JSON.stringify(audios, null, 2));
|
||||
return audios;
|
||||
}
|
||||
|
||||
private static async generateSongs(
|
||||
prompt: string,
|
||||
isCustom: boolean,
|
||||
tags?: string,
|
||||
title?: string,
|
||||
make_instrumental?: boolean,
|
||||
wait_audio: boolean = false
|
||||
): Promise<AudioInfo[]> {
|
||||
const authToken = await this.getAuthToken();
|
||||
const payload: any = {
|
||||
make_instrumental: make_instrumental == true,
|
||||
mv: "chirp-v3-0",
|
||||
prompt: "",
|
||||
};
|
||||
if (isCustom) {
|
||||
payload.tags = tags;
|
||||
payload.title = title;
|
||||
payload.prompt = prompt;
|
||||
} else {
|
||||
payload.gpt_description_prompt = prompt;
|
||||
}
|
||||
console.log("generateSongs payload:\n", {
|
||||
prompt: prompt,
|
||||
isCustom: isCustom,
|
||||
tags: tags,
|
||||
title: title,
|
||||
make_instrumental: make_instrumental,
|
||||
wait_audio: wait_audio,
|
||||
payload: payload,
|
||||
});
|
||||
const response = await axios.post(
|
||||
`${SunoApi.baseUrl}/api/generate/v2/`,
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`,
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
},
|
||||
timeout: 10000, // 10 seconds timeout
|
||||
},
|
||||
);
|
||||
console.log("generateSongs Response:\n", JSON.stringify(response.data, null, 2));
|
||||
if (response.status !== 200) {
|
||||
throw new Error("Error response:" + response.statusText);
|
||||
}
|
||||
const songIds = response.data.clips.map((audio: any) => audio.id);
|
||||
//Want to wait for music file generation
|
||||
if (wait_audio === true) {
|
||||
const startTime = Date.now();
|
||||
let lastResponse: AudioInfo[] = [];
|
||||
await sleep(2, 4);
|
||||
while (Date.now() - startTime < 30000) {
|
||||
const response = await SunoApi.get(songIds);
|
||||
console.log("Waiting for audio Response:\n", JSON.stringify(response, null, 2));
|
||||
const allCompleted = response.every(
|
||||
audio => audio.status === 'streaming' || audio.status === 'complete'
|
||||
);
|
||||
if (allCompleted) {
|
||||
return response;
|
||||
}
|
||||
lastResponse = response;
|
||||
await sleep(2, 4);
|
||||
this.KeepAlive();
|
||||
}
|
||||
return lastResponse;
|
||||
} else {
|
||||
this.KeepAlive();
|
||||
return response.data.clips.map((audio: any) => ({
|
||||
id: audio.id,
|
||||
title: audio.title,
|
||||
image_url: audio.image_url,
|
||||
lyric: audio.metadata.prompt,
|
||||
audio_url: audio.audio_url,
|
||||
video_url: audio.video_url,
|
||||
created_at: audio.created_at,
|
||||
model_name: audio.model_name,
|
||||
status: audio.status,
|
||||
gpt_description_prompt: audio.metadata.gpt_description_prompt,
|
||||
prompt: audio.metadata.prompt,
|
||||
type: audio.metadata.type,
|
||||
tags: audio.metadata.tags,
|
||||
duration: audio.metadata.duration_formatted,
|
||||
}));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 将音频元数据中的歌词(prompt)处理成易于阅读的格式。
|
||||
* @param prompt 原始歌词文本。
|
||||
* @returns 处理后的歌词文本。
|
||||
*/
|
||||
private static parseLyrics(prompt: string): string {
|
||||
// 假设原始歌词是以特定分隔符(例如,换行符)分隔的,我们可以将其转换为更易于阅读的格式。
|
||||
// 这里的实现可以根据实际的歌词格式进行调整。
|
||||
// 例如,如果歌词是以连续的文本形式存在,可能需要根据特定的标记(如句号、逗号等)来分割。
|
||||
// 下面的实现假设歌词已经是以换行符分隔的。
|
||||
|
||||
// 使用换行符分割歌词,并确保移除空行。
|
||||
const lines = prompt.split('\n').filter(line => line.trim() !== '');
|
||||
|
||||
// 将处理后的歌词行重新组合成一个字符串,每行之间用换行符分隔。
|
||||
// 可以在这里添加额外的格式化逻辑,如添加特定的标记或者处理特殊的行。
|
||||
const formattedLyrics = lines.join('\n');
|
||||
|
||||
return formattedLyrics;
|
||||
}
|
||||
public static async get(songIds?: string[]): Promise<AudioInfo[]> {
|
||||
const authToken = await this.getAuthToken();
|
||||
let url = `${SunoApi.baseUrl}/api/feed/`;
|
||||
if (songIds) {
|
||||
url = `${url}?ids=${songIds.join(',')}`;
|
||||
}
|
||||
console.log("Get URL:\n", url);
|
||||
const response = await axios.get(url, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`,
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
},
|
||||
timeout: 3000, // 3 seconds timeout
|
||||
});
|
||||
|
||||
const audios = response.data;
|
||||
console.log("Get Response:\n", JSON.stringify(audios, null, 2));
|
||||
return audios.map((audio: any) => ({
|
||||
id: audio.id,
|
||||
title: audio.title,
|
||||
image_url: audio.image_url,
|
||||
lyric: audio.metadata.prompt ? this.parseLyrics(audio.metadata.prompt) : "",
|
||||
audio_url: audio.audio_url,
|
||||
video_url: audio.video_url,
|
||||
created_at: audio.created_at,
|
||||
model_name: audio.model_name,
|
||||
status: audio.status,
|
||||
gpt_description_prompt: audio.metadata.gpt_description_prompt,
|
||||
prompt: audio.metadata.prompt,
|
||||
type: audio.metadata.type,
|
||||
tags: audio.metadata.tags,
|
||||
duration: audio.metadata.duration_formatted,
|
||||
}));
|
||||
}
|
||||
|
||||
public static async get_limit(): Promise<number> {
|
||||
const authToken = await this.getAuthToken();
|
||||
const response = await axios.get(`${SunoApi.baseUrl}/api/billing/info/`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authToken}`,
|
||||
'User-Agent': SunoApi.userAgent,
|
||||
},
|
||||
});
|
||||
return response.data.total_credits_left;
|
||||
}
|
||||
}
|
||||
|
||||
export default SunoApi;
|
Loading…
Reference in New Issue
Block a user