Something went wrong. Try again.
upload a video to bluesky via the simple method. the video is not pre-processed and thus is not available for a short while after making the post. A better approach is to pre-process the video - see here: https://tangled.sh/strings/samuel.bsky.team/3lw743ejno722
Something went wrong. Try again.
2.0 kB · 71 lines · Created 1y ago
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172// NOTE: this uses Deno
import { AppBskyEmbedVideo, AtpAgent } from "npm:@atproto/api";
const userAgent = new AtpAgent({ service: prompt("Service URL (default: https://bsky.social):") || "https://bsky.social",});
await userAgent.login({ identifier: prompt("Handle:")!, password: prompt("Password:")!,});
console.log(`Logged in as ${userAgent.session?.handle}`);
const videoPath = prompt("Video file (.mp4):")!;
const file = await Deno.open(videoPath);const { size } = await file.stat();
// optional: print upload progresslet bytesUploaded = 0;const progressTrackingStream = new TransformStream({ transform(chunk, controller) { controller.enqueue(chunk); bytesUploaded += chunk.byteLength; console.log( "upload progress:", Math.trunc(bytesUploaded / size * 100) + "%", ); }, flush() { console.log("upload complete ✨"); },});
const { data } = await userAgent.com.atproto.repo.uploadBlob( // @ts-expect-error - expecting an Uint8Array, but a ReadableStream is fine file.readable.pipeThrough(progressTrackingStream),);
console.log("video uploaded, posting...");
await userAgent.post({ text: "This post should have a video attached", langs: ["en"], embed: { $type: "app.bsky.embed.video", video: data.blob, aspectRatio: await getAspectRatio(videoPath), } satisfies AppBskyEmbedVideo.Main,});
console.log("done ✨ (video will take a little bit to process)");
// bonus: get aspect ratio using ffprobe// in the browser, you can just put the video uri in a <video> element// and measure the dimensions once it loads. in React Native, the image picker// will give you the dimensions directly
import { ffprobe } from "https://deno.land/x/fast_forward@0.1.6/ffprobe.ts";
async function getAspectRatio(fileName: string) { const { streams } = await ffprobe(fileName, {}); const videoSteam = streams.find((stream) => stream.codec_type === "video"); return { width: videoSteam.width, height: videoSteam.height, };}