diff --git a/.env.example b/.env.example index be90ebb..90748ce 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ # For more information, please see the README.md SUNO_COOKIE= TWOCAPTCHA_KEY= # Obtain from 2captcha.com -BROWSER=chromium # chromium or firefox, although chromium is highly recommended +BROWSER=chromium # `chromium` or `firefox`, although `chromium` is highly recommended BROWSER_GHOST_CURSOR=false BROWSER_LOCALE=en BROWSER_HEADLESS=true \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 5d9fd2e..9c418f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,32 @@ -# syntax=docker/dockerfile:1 - -FROM node:lts-alpine AS builder -WORKDIR /src -COPY package*.json ./ -RUN npm install -COPY . . -RUN npm run build - -FROM node:lts-alpine -WORKDIR /app -COPY package*.json ./ - -ARG SUNO_COOKIE -ARG BROWSER -RUN if [ -z "$SUNO_COOKIE" ]; then echo "Warning: SUNO_COOKIE is not set"; fi +# syntax=docker/dockerfile:1 + +FROM node:lts-bookworm AS builder +WORKDIR /src +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM node:lts-bookworm +WORKDIR /app +COPY package*.json ./ + +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libnss3 \ + libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \ + libgbm1 libxkbcommon0 libasound2 libcups2 xvfb + +ARG SUNO_COOKIE +RUN if [ -z "$SUNO_COOKIE" ]; then echo "Warning: SUNO_COOKIE is not set. You will have to set the cookies in the Cookie header of your requests."; fi ENV SUNO_COOKIE=${SUNO_COOKIE} -RUN if [ -z "$BROWSER" ]; then echo "Warning: BROWSER is not set; will use chromium by default"; fi -ENV BROWSER=${BROWSER:-chromium} +# Disable GPU acceleration, as with it suno-api won't work in a Docker environment +ENV BROWSER_DISABLE_GPU=true -RUN npm install --only=production -RUN npx playwright install $BROWSER -COPY --from=builder /src/.next ./.next -EXPOSE 3000 -CMD ["npm", "run", "start"] +RUN npm install --only=production + +# Install all supported browsers, else switching browsers requires an image rebuild +RUN npx playwright install chromium +# RUN npx playwright install firefox + +COPY --from=builder /src/.next ./.next +EXPOSE 3000 +CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/README.md b/README.md index 37bebc1..d93d4d0 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,11 @@ We have deployed an example bound to a free Suno account, so it has daily usage [Create](https://2captcha.com/auth/register?userType=customer) a new 2Captcha account, [top up](https://2captcha.com/pay) your balance and [get your API key](https://2captcha.com/enterpage#recognition). -If you are located in Russia or Belarus, use the [ruCaptcha](https://rucaptcha.com) interface instead of 2Captcha. It's the same service, but it supports payments from those countries. +> [!NOTE] +> If you are located in Russia or Belarus, use the [ruCaptcha](https://rucaptcha.com) interface instead of 2Captcha. It's the same service, but it supports payments from those countries. + +> [!TIP] +> If you want as few CAPTCHAs as possible, it is recommended to use a macOS system. macOS systems usually get fewer CAPTCHAs than Linux and Windows—this is due to its unpopularity in the web scraping industry. Running suno-api on Windows and Linux will work, but in some cases, you could get a pretty large number of CAPTCHAs. ### 3. Clone and deploy this project @@ -80,9 +84,11 @@ You can choose your preferred deployment method: git clone https://github.com/gcui-art/suno-api.git cd suno-api npm install -npx playwright install chromium ``` #### Docker +>[!IMPORTANT] +> GPU acceleration will be disabled in Docker. If you have a slow CPU, it is recommended to [deploy locally](#run-locally). + Alternatively, you can use [Docker Compose](https://docs.docker.com/compose/). However, follow the step below before running. ```bash diff --git a/README_RU.md b/README_RU.md index 859db8e..4a5d6f2 100644 --- a/README_RU.md +++ b/README_RU.md @@ -64,7 +64,11 @@ Suno — потрясающий сервис для ИИ-музыки. Несм [Создайте](https://2captcha.com/ru/auth/register?userType=customer) новый аккаунт, [пополните](https://2captcha.com/ru/pay) баланс и [получите свой API-ключ](https://2captcha.com/ru/enterpage#recognition). -ℹ Если вы находитесь в России или Беларуси, используйте интерфейс [ruCaptcha](https://rucaptcha.com) вместо 2Captcha. Это абсолютно тот же сервис, но данный интерфейс поддерживает платежи из этих стран. +> [!NOTE] +> Если вы находитесь в России или Беларуси, используйте интерфейс [ruCaptcha](https://rucaptcha.com) вместо 2Captcha. Это абсолютно тот же сервис, но данный интерфейс поддерживает платежи из этих стран. + +> [!TIP] +> Если вы хотите получать как можно меньше капч, рекомендуется использовать macOS. Системы на macOS обычно получают меньше капч, чем Linux и Windows — это связано с их непопулярностью в сфере веб-скрейпинга. Запуск suno-api на Windows и Linux будет работать, но в некоторых случаях вы можете получить довольно большое количество капч. ### 3. Скачайте и запустите проект @@ -80,9 +84,10 @@ Suno — потрясающий сервис для ИИ-музыки. Несм git clone https://github.com/gcui-art/suno-api.git cd suno-api npm install -npx playwright install chromium ``` #### Docker +>[!IMPORTANT] +> Аппаратное видеоускорение браузера будет отключено в Docker. Если у вас медленный процессор, рекомендуется [развернуть локально](#локально). Также можно использовать [Docker Compose](https://docs.docker.com/compose/), однако перед запуском выполните шаг ниже. ```bash diff --git a/docker-compose.yml b/docker-compose.yml index dfeb46f..df54c95 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,3 +10,4 @@ services: - ./public:/app/public ports: - "3000:3000" + env_file: ".env" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4cfc7d2..bd0ec7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "LGPL-3.0-or-later", "dependencies": { "@2captcha/captcha-solver": "^1.3.0", + "@playwright/browser-chromium": "^1.49.1", "@vercel/analytics": "^1.2.2", "axios": "^1.7.8", "bufferutil": "^4.0.8", @@ -602,6 +603,19 @@ "node": ">=14" } }, + "node_modules/@playwright/browser-chromium": { + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.49.1.tgz", + "integrity": "sha512-LLeyllKSucbojsJBOpdJshwW27ZXZs3oypqffkVWLUvxX2azHJMOevsOcWpjCfoYbpevkaEozM2xHeSUGF00lg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.49.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", diff --git a/package.json b/package.json index deeb8ec..efd925e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@2captcha/captcha-solver": "^1.3.0", + "@playwright/browser-chromium": "^1.49.1", "@vercel/analytics": "^1.2.2", "axios": "^1.7.8", "bufferutil": "^4.0.8", diff --git a/src/lib/SunoApi.ts b/src/lib/SunoApi.ts index 51a4e6f..75e6bd7 100644 --- a/src/lib/SunoApi.ts +++ b/src/lib/SunoApi.ts @@ -230,17 +230,23 @@ class SunoApi { * @returns {BrowserContext} */ private async launchBrowser(): Promise { + const args = [ + '--disable-blink-features=AutomationControlled', + '--disable-web-security', + '--no-sandbox', + '--disable-dev-shm-usage', + '--disable-features=site-per-process', + '--disable-features=IsolateOrigins', + '--disable-extensions', + '--disable-infobars' + ]; + // Check for GPU acceleration, as it is recommended to turn it off for Docker + if (yn(process.env.BROWSER_DISABLE_GPU, { default: false })) + args.push('--enable-unsafe-swiftshader', + '--disable-gpu', + '--disable-setuid-sandbox'); const browser = await this.getBrowserType().launch({ - args: [ - '--disable-blink-features=AutomationControlled', - '--disable-web-security', - '--no-sandbox', - '--disable-dev-shm-usage', - '--disable-features=site-per-process', - '--disable-features=IsolateOrigins', - '--disable-extensions', - '--disable-infobars' - ], + args, headless: yn(process.env.BROWSER_HEADLESS, { default: true }) }); const context = await browser.newContext({ userAgent: this.userAgent, locale: process.env.BROWSER_LOCALE, viewport: null }); @@ -798,7 +804,7 @@ class SunoApi { } export const sunoApi = async (cookie?: string) => { - const resolvedCookie = cookie || process.env.SUNO_COOKIE; + const resolvedCookie = cookie && cookie.includes('__client') ? cookie : process.env.SUNO_COOKIE; // Check for bad `Cookie` header (It's too expensive to actually parse the cookies *here*) if (!resolvedCookie) { logger.info('No cookie provided! Aborting...\nPlease provide a cookie either in the .env file or in the Cookie header of your request.') throw new Error('Please provide a cookie either in the .env file or in the Cookie header of your request.');