Merge branch 'imputnet:main' into main

This commit is contained in:
Spax 2024-09-13 16:37:12 -06:00 committed by GitHub
commit 81c5f29b3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 86 additions and 27 deletions

6
.github/test.sh vendored
View file

@ -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 $?

View file

@ -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);

View file

@ -148,6 +148,7 @@ export default function({ r, host, audioFormat, isAudioOnly, isAudioMuted, disab
case "streamable":
case "snapchat":
case "loom":
case "twitch":
responseType = "redirect";
break;
}

View file

@ -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 });
}

View file

@ -18,8 +18,8 @@ const codecMatch = {
},
av1: {
videoCodec: "av01",
audioCodec: "mp4a",
container: "mp4"
audioCodec: "opus",
container: "webm"
},
vp9: {
videoCodec: "vp9",

View file

@ -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"
}
}
]
}

View file

@ -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`.

View file

@ -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",

View file

@ -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.

View file

@ -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>