mirror of
https://github.com/wukko/cobalt.git
synced 2024-11-15 12:50:01 +00:00
api: add audio bitrate functionality
This commit is contained in:
parent
fb5d68a830
commit
91fd26e880
6 changed files with 38 additions and 22 deletions
|
@ -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,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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", {
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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), {
|
||||||
|
|
Loading…
Reference in a new issue