Last active
April 4, 2025 09:37
-
-
Save shahmal1yev/edef78f9a8c6f711ffde0abb87435438 to your computer and use it in GitHub Desktop.
Bluesky PHP Video Upload Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Atproto\Client; | |
use Atproto\DataModel\Blob\Blob; | |
use Atproto\Lexicons\App\Bsky\Embed\Video; | |
use Atproto\Responses\App\Bsky\Video\UploadVideoResponse; | |
use Atproto\Support\FileSupport; | |
// Authenticate the client with Bluesky credentials | |
$client = new Client(); | |
$client->authenticate('your-handle.bsky.social', 'your-password'); | |
// Retrieve the PDS server url from the authenticated session | |
$pdsUrl = null; | |
foreach ($client->authenticated()->didDoc()['service'] ?? [] as $service) { | |
if (($service['id'] ?? null) === '#atproto_pds') { | |
$pdsUrl = $service['serviceEndpoint'] ?? null; | |
break; | |
} | |
} | |
if (! $pdsUrl) { | |
throw new LogicException("Could not resolve PDS endpoint from DID document."); // If this happens, please report it | |
} | |
// Extract the host part from the PDS endpoint | |
$pdsHost = str_replace( | |
["https://", "http://"], | |
"did:web:", | |
$pdsUrl | |
); | |
// Generate a temporary authentication token for uploading the video | |
$token = bskyFacade($client)->getServiceAuth() | |
->aud($pdsHost) | |
->lxm(bskyFacade()->uploadBlob()->nsid()) | |
->exp(\Carbon\Carbon::now()->addMinutes(15)->timestamp) | |
->send() | |
->token(); | |
// Define the video file path | |
$filePath = '/path/to/your/video.mp4'; | |
$file = new FileSupport($filePath); | |
// Upload the video to Bluesky | |
$uploadedVideo = bskyFacade()->uploadVideo(basename($filePath), $file, $token)->send(); | |
// Check if the upload response includes a video blob reference | |
$videoBlob = null; | |
if ($uploadedVideo->has('blob')) { | |
$videoBlob = Blob::viaArray($uploadedVideo->blob()); | |
} | |
// If the video blob is not immediately available, wait for job completion | |
while (! $videoBlob) { | |
$jobStatusResponse = bskyFacade()->getJobStatus($uploadedVideo->jobId())->send(); | |
// If the upload job has completed, retrieve the video blob | |
if ($jobStatusResponse->jobStatus()->state() === 'JOB_STATE_COMPLETED') { | |
$videoBlob = Blob::viaArray($jobStatusResponse->jobStatus()->blob()); | |
} | |
// Wait briefly before checking again | |
sleep(0.5); | |
} | |
// Create a new post with the uploaded video | |
$post = bskyFacade()->post() | |
->text("Hello, BlueSky! This is a video.") | |
->embed(new Video($videoBlob)); | |
// Publish the post and retrieve the created post's URI | |
$createdRecordRes = bskyFacade()->createRecord() | |
->repo($client->authenticated()->handle()) | |
->collection($post->nsid()) | |
->record($post) | |
->send(); | |
// Construct the public URL of the posted video | |
$username = $client->authenticated()->handle(); | |
$postNsid = $post->nsid(); | |
$segments = explode("/", $createdRecordRes->uri()); | |
$postId = end($segments); | |
$uri = "https://bsky.app/profile/$username/post/$postId"; | |
// Output the post URL | |
echo $uri . PHP_EOL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment