api: add audio bitrate functionality

This commit is contained in:
wukko 2024-08-22 19:35:17 +06:00
parent fb5d68a830
commit 91fd26e880
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2
6 changed files with 38 additions and 22 deletions

View file

@ -1,12 +1,5 @@
const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"; const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
const supportedAudio = ["mp3", "ogg", "wav", "opus"]; const supportedAudio = ["mp3", "ogg", "wav", "opus"];
const ffmpegArgs = {
webm: ["-c:v", "copy", "-c:a", "copy"],
mp4: ["-c:v", "copy", "-c:a", "copy", "-movflags", "faststart+frag_keyframe+empty_moov"],
audio: ["-ar", "48000", "-ac", "2", "-b:a", "320k"],
m4a: ["-movflags", "frag_keyframe+empty_moov"],
gif: ["-vf", "scale=-1:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse", "-loop", "0"]
}
const env = { const env = {
apiURL: process.env.API_URL || '', apiURL: process.env.API_URL || '',
@ -42,5 +35,4 @@ export {
genericUserAgent, genericUserAgent,
supportedAudio, supportedAudio,
ffmpegArgs,
} }

View file

@ -5,7 +5,7 @@ import { createResponse } from "./request.js";
import { createStream } from "../stream/manage.js"; import { createStream } from "../stream/manage.js";
import { audioIgnore, services } from "./service-config.js"; import { audioIgnore, services } from "./service-config.js";
export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disableMetadata, filenameStyle, twitterGif, requestIP }) { export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disableMetadata, filenameStyle, twitterGif, requestIP, audioBitrate }) {
let action, let action,
responseType = "stream", responseType = "stream",
defaultParams = { defaultParams = {
@ -193,8 +193,10 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
params = { params = {
type: processType, type: processType,
u: Array.isArray(r.urls) ? r.urls[1] : r.urls, u: Array.isArray(r.urls) ? r.urls[1] : r.urls,
audioFormat: audioFormat,
copy: copy audioBitrate,
audioCopy: copy,
audioFormat,
} }
break; break;
} }

View file

@ -261,7 +261,8 @@ export default async function(host, patternMatch, obj) {
disableMetadata, disableMetadata,
filenameStyle: obj.filenameStyle, filenameStyle: obj.filenameStyle,
twitterGif: obj.twitterGif, twitterGif: obj.twitterGif,
requestIP requestIP,
audioBitrate: obj.audioBitrate,
}) })
} catch { } catch {
return createResponse("error", { return createResponse("error", {

View file

@ -8,6 +8,10 @@ export const apiSchema = z.object({
.min(1) .min(1)
.transform((url) => normalizeURL(decodeURIComponent(url))), .transform((url) => normalizeURL(decodeURIComponent(url))),
audioBitrate: z.enum(
["320", "256", "128", "96", "64"]
).default("256"),
audioFormat: z.enum( audioFormat: z.enum(
["best", "mp3", "ogg", "wav", "opus"] ["best", "mp3", "ogg", "wav", "opus"]
).default("mp3"), ).default("mp3"),

View file

@ -37,11 +37,15 @@ export function createStream(obj) {
urls: obj.u, urls: obj.u,
service: obj.service, service: obj.service,
filename: obj.filename, filename: obj.filename,
audioFormat: obj.audioFormat,
requestIP: obj.requestIP,
headers: obj.headers, headers: obj.headers,
copy: !!obj.copy,
metadata: obj.fileMetadata || false, metadata: obj.fileMetadata || false,
requestIP: obj.requestIP
audioBitrate: obj.audioBitrate,
audioCopy: !!obj.audioCopy,
audioFormat: obj.audioFormat,
}; };
streamCache.set( streamCache.set(

View file

@ -3,12 +3,19 @@ import ffmpeg from "ffmpeg-static";
import { spawn } from "child_process"; import { spawn } from "child_process";
import { create as contentDisposition } from "content-disposition-header"; import { create as contentDisposition } from "content-disposition-header";
import { env, ffmpegArgs } from "../config.js"; import { env } from "../config.js";
import { metadataManager } from "../misc/utils.js"; import { metadataManager } from "../misc/utils.js";
import { destroyInternalStream } from "./manage.js"; import { destroyInternalStream } from "./manage.js";
import { hlsExceptions } from "../processing/service-config.js"; import { hlsExceptions } from "../processing/service-config.js";
import { getHeaders, closeRequest, closeResponse, pipe } from "./shared.js"; import { getHeaders, closeRequest, closeResponse, pipe } from "./shared.js";
const ffmpegArgs = {
webm: ["-c:v", "copy", "-c:a", "copy"],
mp4: ["-c:v", "copy", "-c:a", "copy", "-movflags", "faststart+frag_keyframe+empty_moov"],
m4a: ["-movflags", "frag_keyframe+empty_moov"],
gif: ["-vf", "scale=-1:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse", "-loop", "0"]
}
const toRawHeaders = (headers) => { const toRawHeaders = (headers) => {
return Object.entries(headers) return Object.entries(headers)
.map(([key, value]) => `${key}: ${value}\r\n`) .map(([key, value]) => `${key}: ${value}\r\n`)
@ -209,18 +216,24 @@ const convertAudio = (streamInfo, res) => {
'-vn' '-vn'
) )
if (streamInfo.metadata) { if (streamInfo.audioCopy) {
args = args.concat(metadataManager(streamInfo.metadata)) args.push("-c:a", "copy")
} else {
args.push("-b:a", `${streamInfo.audioBitrate}k`)
} }
args = args.concat( if (streamInfo.audioFormat === "opus") {
streamInfo.copy ? ["-c:a", "copy"] : ffmpegArgs.audio args.push("-vbr", "off")
); }
if (ffmpegArgs[streamInfo.audioFormat]) { if (ffmpegArgs[streamInfo.audioFormat]) {
args = args.concat(ffmpegArgs[streamInfo.audioFormat]) args = args.concat(ffmpegArgs[streamInfo.audioFormat])
} }
if (streamInfo.metadata) {
args = args.concat(metadataManager(streamInfo.metadata))
}
args.push('-f', streamInfo.audioFormat === "m4a" ? "ipod" : streamInfo.audioFormat, 'pipe:3'); args.push('-f', streamInfo.audioFormat === "m4a" ? "ipod" : streamInfo.audioFormat, 'pipe:3');
process = spawn(...getCommand(args), { process = spawn(...getCommand(args), {
@ -257,7 +270,7 @@ const convertGif = (streamInfo, res) => {
} }
args.push('-i', streamInfo.urls); args.push('-i', streamInfo.urls);
args = args.concat(ffmpegArgs["gif"]); args = args.concat(ffmpegArgs.gif);
args.push('-f', "gif", 'pipe:3'); args.push('-f', "gif", 'pipe:3');
process = spawn(...getCommand(args), { process = spawn(...getCommand(args), {