Skip to content

Commit

Permalink
New process to upload a broadcast replay to IGTV
Browse files Browse the repository at this point in the history
  • Loading branch information
omouren committed Jan 31, 2021
1 parent f232296 commit 35361e8
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 37 deletions.
129 changes: 129 additions & 0 deletions examples/live-replay-to-igtv.example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* tslint:disable:no-console */
import {IgApiClient, LiveEntity} from '../src';
import Bluebird = require('bluebird');
const pngToJpeg = require('png-to-jpeg')
const sharp = require('sharp');
const https = require('https');

const ig = new IgApiClient();

async function login() {
ig.state.generateDevice(process.env.IG_USERNAME);
ig.state.proxyUrl = process.env.IG_PROXY;
await ig.account.login(process.env.IG_USERNAME, process.env.IG_PASSWORD);
}

(async () => {
// basic login-procedure
await login();

const {broadcast_id, upload_url} = await ig.live.create({
// create a stream in 720x1280 (9:16)
previewWidth: 720,
previewHeight: 1280,
// this message is not necessary, because it doesn't show up in the notification
message: 'My message',
});
// (optional) get the key and url for programs such as OBS
const {stream_key, stream_url} = LiveEntity.getUrlAndKey({broadcast_id, upload_url});
console.log(`Start your stream on ${stream_url}.\n
Your key is: ${stream_key}`);

/**
* make sure you are streaming to the url
* the next step will send a notification / start your stream for everyone to see
*/
const startInfo = await ig.live.start(broadcast_id);
// status should be 'ok'
console.log(startInfo);

/**
* now, your stream is running
* the next step is to get comments
* note: comments can only be requested roughly every 2s
*/

// initial comment-timestamp = 0, get all comments
let lastCommentTs = await printComments(broadcast_id, 0);

// enable the comments
await ig.live.unmuteComment(broadcast_id);
/**
* wait 2 seconds until the next request.
* in the real world you'd use something like setInterval() instead of Bluebird.delay() / just to simulate a delay
*/
// wait 2s
await Bluebird.delay(2000);
// now, we print the next comments
lastCommentTs = await printComments(broadcast_id, lastCommentTs);

// now we're commenting on our stream
await ig.live.comment(broadcast_id, 'A comment');

/**
* now, your stream is running, you entertain your followers, but you're tired and
* we're going to stop the stream
*/
await ig.live.endBroadcast(broadcast_id);

// Get live thumbnails, required to post on IGTV
let data = await ig.live.getPostLiveThumbnails(broadcast_id)

// Download any thumb
let file = await new Promise((resolve) => https.get(data.thumbnails[0], (download) => {
let ds = [];
download.on("data", (d) => ds.push(d));
download.on("end", () => resolve(Buffer.concat(ds)))
}))

// (optional) Resize thumb to a vertical one
file = await sharp(file)
.resize(720, 1280)
.png()
.toBuffer()

// It will be a png, it must be converted to jpg
file = await pngToJpeg({quality: 100})(file)

// Upload the thumbnail with a broadcast id for a replay and get uploadId
let upload = await ig.upload.photo({file, broadcastId: broadcast_id})

let igtv = null
let currentRetry = 0
let maxRetry = 3
let retryDelay = 4
while (!igtv) {
// This endpoint can return an error "202 Accepted; Transcode not finished yet" if Instagram has not finished to process the previous upload, so retry later in this case
try {
igtv = await ig.media.configureToIgtv({
upload_id: upload.upload_id,
title: 'A title',
caption: 'A description',
igtv_share_preview_to_feed: '1',
})

console.log(`Live posted to IGTV : ${igtv.upload_id}`))
} catch (e) {
currentRetry++
if (currentRetry > maxRetry) {
throw e
} else {
await (new Promise(resolve => {
setTimeout(resolve, currentRetry * retryDelay)
}))
}
}
}

// now you're basically done
})();

async function printComments(broadcastId, lastCommentTs) {
const {comments} = await ig.live.getComment({broadcastId, lastCommentTs});
if (comments.length > 0) {
comments.forEach(comment => console.log(`${comment.user.username}: ${comment.text}`));
return comments[comments.length - 1].created_at;
} else {
return lastCommentTs;
}
}
31 changes: 0 additions & 31 deletions src/repositories/live.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
LiveSwitchCommentsResponseRootObject,
LiveCreateBroadcastResponseRootObject,
LiveStartBroadcastResponseRootObject,
LiveAddPostLiveToIgtvResponseRootObject,
LiveCommentsResponseRootObject,
LiveHeartbeatViewerCountResponseRootObject,
LiveInfoResponseRootObject,
Expand Down Expand Up @@ -281,36 +280,6 @@ export class LiveRepository extends Repository {
return body;
}

public async addPostLiveToIgtv({
broadcastId,
title,
description,
coverUploadId,
igtvSharePreviewToFeed = false,
}: {
broadcastId: string;
title: string;
description: string;
coverUploadId: string;
igtvSharePreviewToFeed?: boolean;
}): Promise<LiveAddPostLiveToIgtvResponseRootObject> {
const { body } = await this.client.request.send<LiveAddPostLiveToIgtvResponseRootObject>({
url: `/api/v1/live/add_post_live_to_igtv/`,
method: 'POST',
form: this.client.request.sign({
_csrftoken: this.client.state.cookieCsrfToken,
_uuid: this.client.state.uuid,
broadcast_id: broadcastId,
cover_upload_id: coverUploadId,
description: description,
title: title,
internal_only: false,
igtv_share_preview_to_feed: igtvSharePreviewToFeed,
}),
});
return body;
}

public async endBroadcast(broadcastId: string, endAfterCopyrightWarning: boolean = false) {
const { body } = await this.client.request.send({
url: `/api/v1/live/${broadcastId}/end_broadcast/`,
Expand Down
4 changes: 4 additions & 0 deletions src/repositories/upload.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ export class UploadRepository extends Repository {
if (options.isSidecar) {
ruploadParams.is_sidecar = '1';
}
if (options.broadcastId) {
ruploadParams.broadcast_id = options.broadcastId;
ruploadParams.is_post_live_igtv = '1';
}
return ruploadParams;
}

Expand Down
1 change: 0 additions & 1 deletion src/responses/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export * from './live.like-count.response';
export * from './live.post-live-thumbnails.response';
export * from './live.like.response';
export * from './live.start-broadcast.response';
export * from './live.add-post-live-to-igtv.response';
export * from './live.switch-comments.response';
export * from './live.viewer-list.response';
export * from './live.add-to-post.response';
Expand Down
5 changes: 0 additions & 5 deletions src/responses/live.add-post-live-to-igtv.response.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/types/upload.photo.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export interface UploadPhotoOptions {
file: Buffer;
isSidecar?: boolean;
waterfallId?: string;
broadcastId?: string;
}

0 comments on commit 35361e8

Please sign in to comment.