mirror of
https://github.com/wukko/cobalt.git
synced 2025-01-27 05:06:18 +01:00
Merge branch 'imputnet:main' into main
This commit is contained in:
commit
81c5f29b3a
10 changed files with 86 additions and 27 deletions
6
.github/test.sh
vendored
6
.github/test.sh
vendored
|
@ -14,7 +14,7 @@ waitport() {
|
|||
test_api() {
|
||||
waitport 3000
|
||||
curl -m 3 http://localhost:3000/
|
||||
API_RESPONSE=$(curl -m 3 http://localhost:3000/ \
|
||||
API_RESPONSE=$(curl -m 10 http://localhost:3000/ \
|
||||
-X POST \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
|
@ -24,7 +24,7 @@ test_api() {
|
|||
STATUS=$(echo "$API_RESPONSE" | jq -r .status)
|
||||
STREAM_URL=$(echo "$API_RESPONSE" | jq -r .url)
|
||||
[ "$STATUS" = tunnel ] || exit 1;
|
||||
S=$(curl -I -m 3 "$STREAM_URL")
|
||||
S=$(curl -I -m 10 "$STREAM_URL")
|
||||
|
||||
CONTENT_LENGTH=$(echo "$S" \
|
||||
| grep -i content-length \
|
||||
|
@ -64,4 +64,4 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
wait || exit $?
|
||||
wait || exit $?
|
||||
|
|
|
@ -2,11 +2,19 @@ export default (f, style, isAudioOnly, isAudioMuted) => {
|
|||
let filename = '';
|
||||
|
||||
let infoBase = [f.service, f.id];
|
||||
let classicTags = [...infoBase, f.resolution];
|
||||
let basicTags = [f.qualityLabel];
|
||||
let classicTags = [...infoBase];
|
||||
let basicTags = [];
|
||||
|
||||
const title = `${f.title} - ${f.author}`;
|
||||
|
||||
if (f.resolution) {
|
||||
classicTags.push(f.resolution);
|
||||
}
|
||||
|
||||
if (f.qualityLabel) {
|
||||
basicTags.push(f.qualityLabel);
|
||||
}
|
||||
|
||||
if (f.youtubeFormat) {
|
||||
classicTags.push(f.youtubeFormat);
|
||||
basicTags.push(f.youtubeFormat);
|
||||
|
|
|
@ -148,6 +148,7 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
|
|||
case "streamable":
|
||||
case "snapchat":
|
||||
case "loom":
|
||||
case "twitch":
|
||||
responseType = "redirect";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ import HLS from "hls-parser";
|
|||
import { cobaltUserAgent } from "../../config.js";
|
||||
import { createStream } from "../../stream/manage.js";
|
||||
|
||||
const extractVideo = async ({ getPost, filename }) => {
|
||||
const urlMasterHLS = getPost?.thread?.post?.embed?.playlist;
|
||||
const extractVideo = async ({ media, filename }) => {
|
||||
const urlMasterHLS = media?.playlist;
|
||||
if (!urlMasterHLS) return { error: "fetch.empty" };
|
||||
if (!urlMasterHLS.startsWith("https://video.bsky.app/")) return { error: "fetch.empty" };
|
||||
|
||||
|
@ -77,14 +77,37 @@ export default async function ({ user, post, alwaysProxy }) {
|
|||
}
|
||||
}).then(r => r.json()).catch(() => {});
|
||||
|
||||
if (!getPost || getPost?.error) return { error: "fetch.empty" };
|
||||
if (!getPost) return { error: "fetch.empty" };
|
||||
|
||||
if (getPost.error) {
|
||||
switch (getPost.error) {
|
||||
case "NotFound":
|
||||
case "InternalServerError":
|
||||
return { error: "content.post.unavailable" };
|
||||
case "InvalidRequest":
|
||||
return { error: "link.unsupported" };
|
||||
default:
|
||||
return { error: "fetch.empty" };
|
||||
}
|
||||
}
|
||||
|
||||
const embedType = getPost?.thread?.post?.embed?.$type;
|
||||
const filename = `bluesky_${user}_${post}`;
|
||||
|
||||
if (embedType === "app.bsky.embed.video#view") {
|
||||
return extractVideo({ getPost, filename });
|
||||
return extractVideo({
|
||||
media: getPost.thread?.post?.embed,
|
||||
filename,
|
||||
})
|
||||
}
|
||||
|
||||
if (embedType === "app.bsky.embed.recordWithMedia#view") {
|
||||
return extractVideo({
|
||||
media: getPost.thread?.post?.embed?.media,
|
||||
filename,
|
||||
})
|
||||
}
|
||||
|
||||
if (embedType === "app.bsky.embed.images#view") {
|
||||
return extractImages({ getPost, filename, alwaysProxy });
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ const codecMatch = {
|
|||
},
|
||||
av1: {
|
||||
videoCodec: "av01",
|
||||
audioCodec: "mp4a",
|
||||
container: "mp4"
|
||||
audioCodec: "opus",
|
||||
container: "webm"
|
||||
},
|
||||
vp9: {
|
||||
videoCodec: "vp9",
|
||||
|
|
|
@ -1113,7 +1113,7 @@
|
|||
"params": {},
|
||||
"expected": {
|
||||
"code": 200,
|
||||
"status": "tunnel"
|
||||
"status": "redirect"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1401,7 +1401,16 @@
|
|||
"bsky": [
|
||||
{
|
||||
"name": "horizontal video",
|
||||
"url": "https://bsky.app/profile/samuel.bsky.team/post/3l2udah76ch2c",
|
||||
"url": "https://bsky.app/profile/haileyok.com/post/3l3giwtwp222m",
|
||||
"params": {},
|
||||
"expected": {
|
||||
"code": 200,
|
||||
"status": "tunnel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "horizontal video, recordWithMedia",
|
||||
"url": "https://bsky.app/profile/juicysteak117.gay/post/3l3wonhk23g2i",
|
||||
"params": {},
|
||||
"expected": {
|
||||
"code": 200,
|
||||
|
@ -1410,7 +1419,7 @@
|
|||
},
|
||||
{
|
||||
"name": "vertical video",
|
||||
"url": "https://bsky.app/profile/samuel.bsky.team/post/3l2uftgmitr2p",
|
||||
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
|
||||
"params": {},
|
||||
"expected": {
|
||||
"code": 200,
|
||||
|
@ -1419,7 +1428,7 @@
|
|||
},
|
||||
{
|
||||
"name": "vertical video (muted)",
|
||||
"url": "https://bsky.app/profile/samuel.bsky.team/post/3l2uftgmitr2p",
|
||||
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
|
||||
"params": {
|
||||
"downloadMode": "mute"
|
||||
},
|
||||
|
@ -1430,7 +1439,7 @@
|
|||
},
|
||||
{
|
||||
"name": "vertical video (audio)",
|
||||
"url": "https://bsky.app/profile/samuel.bsky.team/post/3l2uftgmitr2p",
|
||||
"url": "https://bsky.app/profile/haileyok.com/post/3l3jhpomhjk2m",
|
||||
"params": {
|
||||
"downloadMode": "audio"
|
||||
},
|
||||
|
@ -1456,6 +1465,15 @@
|
|||
"code": 200,
|
||||
"status": "picker"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "deleted post/invalid user",
|
||||
"url": "https://bsky.app/profile/notreal.bsky.team/post/3l2udah76ch2c",
|
||||
"params": {},
|
||||
"expected": {
|
||||
"code": 400,
|
||||
"status": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -32,13 +32,19 @@ cobalt package will update automatically thanks to watchtower.
|
|||
|
||||
it's highly recommended to use a reverse proxy (such as nginx) if you want your instance to face the public internet. look up tutorials online.
|
||||
|
||||
## using regular node.js (useful for local development)
|
||||
setup script installs all needed `npm` dependencies, but you have to install `node.js` *(version 18 or above)* and `git` yourself.
|
||||
## run cobalt api outside of docker (useful for local development)
|
||||
requirements:
|
||||
- node.js >= 18
|
||||
- git
|
||||
- pnpm
|
||||
|
||||
1. clone the repo: `git clone https://github.com/imputnet/cobalt`.
|
||||
2. run setup script and follow instructions: `npm run setup`. you need to host api and web instances separately, so pick whichever applies.
|
||||
3. run cobalt via `npm start`.
|
||||
4. done.
|
||||
2. go to api/src directory: `cd cobalt/api/src`.
|
||||
3. install dependencies: `pnpm install`.
|
||||
4. create `.env` file in the same directory.
|
||||
5. add needed environment variables to `.env` file. only `API_URL` is required to run cobalt.
|
||||
- if you don't know what api url to use for local development, use `http://localhost:9000/`.
|
||||
6. run cobalt: `pnpm start`.
|
||||
|
||||
### ubuntu 22.04 workaround
|
||||
`nscd` needs to be installed and running so that the `ffmpeg-static` binary can resolve DNS ([#101](https://github.com/imputnet/cobalt/issues/101#issuecomment-1494822258)):
|
||||
|
@ -72,4 +78,4 @@ sudo service nscd start
|
|||
setting a `FREEBIND_CIDR` allows cobalt to pick a random IP for every download and use it for all
|
||||
requests it makes for that particular download. to use freebind in cobalt, you need to follow its [setup instructions](https://github.com/imputnet/freebind.js?tab=readme-ov-file#setup) first. if you configure this option while running cobalt
|
||||
in a docker container, you also need to set the `API_LISTEN_ADDRESS` env to `127.0.0.1`, and set
|
||||
`network_mode` for the container to `host`.
|
||||
`network_mode` for the container to `host`.
|
||||
|
|
|
@ -30,9 +30,6 @@
|
|||
"video.quality.description": "if preferred video quality isn't available, next best is picked instead.",
|
||||
|
||||
"video.youtube.codec": "youtube video codec and container",
|
||||
"video.youtube.codec.h264": "h264 (mp4)",
|
||||
"video.youtube.codec.av1": "av1 (mp4)",
|
||||
"video.youtube.codec.vp9": "vp9 (webm)",
|
||||
"video.youtube.codec.description": "h264: best compatibility, average bitrate. max quality is 1080p. \nav1: best quality, efficiency, and bitrate. supports 8k & HDR. \nvp9: same quality & bitrate as av1, but file is approximately two times bigger. supports 4k & HDR.\n\nav1 and vp9 aren't as widely supported as h264.",
|
||||
|
||||
"video.twitter.gif": "twitter/x",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<h3>leading privacy</h3>
|
||||
<p>
|
||||
all requests to backend are anonymous and all tunnels are encrypted.
|
||||
we have a strict zero log policy and don't track <i>anything at all</i>.
|
||||
we have a strict zero log policy and don't track <i>anything</i> about individual people.
|
||||
</p>
|
||||
<p>
|
||||
to avoid caching or storing downloaded files, cobalt processes them on-fly, sending processed pieces directly to client.
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
import Switcher from "$components/buttons/Switcher.svelte";
|
||||
import SettingsButton from "$components/buttons/SettingsButton.svelte";
|
||||
import SettingsToggle from "$components/buttons/SettingsToggle.svelte";
|
||||
|
||||
const codecTitles = {
|
||||
h264: "h264 (mp4)",
|
||||
av1: "av1 (webm)",
|
||||
vp9: "vp9 (webm)",
|
||||
}
|
||||
</script>
|
||||
|
||||
<SettingsCategory
|
||||
|
@ -41,7 +47,7 @@
|
|||
settingId="youtubeVideoCodec"
|
||||
settingValue={value}
|
||||
>
|
||||
{$t(`settings.video.youtube.codec.${value}`)}
|
||||
{codecTitles[value]}
|
||||
</SettingsButton>
|
||||
{/each}
|
||||
</Switcher>
|
||||
|
|
Loading…
Reference in a new issue