Create Presentation Slides with AI
Automating Google Slides — infused with OpenAI and Midjourney
Designing and populating slides can take up a lot of time, but advances in Artificial Intelligence have made it possible to create visually stunning and effective presentations much faster.
In this article, we’ll explore how to automate Google Slides and enhance presentations using AI tools like Midjourney and the OpenAI API.
High Level Overview
- Authenticating with Google APIs
- Using a Google Slides Template
- Replacing template text with OpenAI API and images with Midjourney
1. Authentication with Service Account’s Private Key
We begin by importing the googleapis
library and the private key
file of your service account, for authentication and authorization purposes to ensure secure communication between your code and Google services.
const {google} = require('googleapis');
const privatekey = require('./YOUR_SERVICE_ACCOUNT_PRIVATE_KEY.json');
The const {google} = require('googleapis')
line is using destructuring to extract the google
object from the googleapis
library, which provides a convenient way to access and work with Google APIs.
const privatekey = require('./YOUR_SERVICE_ACCOUNT_PRIVATE_KEY.json')
is importing the private key
file of your service account.
A service account is a special type of Google account that is used for non-human processes and applications to access Google APIs.
Google Slides Authentication
const authSlides = new google.auth.JWT(
privatekey.client_email,
null,
privatekey.private_key,
"https://www.googleapis.com/auth/presentations",
null
);
This code is creating a JSON Web Token (JWT) object for authorization to access Google Slides API using the google-auth-library
package. The privatekey
object contains the private key of a service account, which is used to authenticate the request to access Google Slides API.
The new google.auth.JWT()
constructor takes several parameters including the client email, private key, and scope. The client_email
is the email address of the service account and the private_key
is the private key of the service account. The https://www.googleapis.com/auth/presentations
scope specifies that the authorization is for the Google Slides API.
Once the JWT object is created, it can be used to authenticate and authorize API requests to Google Slides on behalf of the service account.
Google Drive Authentication
Similarly, we can do this same for Google Drive, by changing the scope to https://www.googleapis.com/auth/drive
const authDrive = new google.auth.JWT(
privatekey.client_email,
null,
privatekey.private_key,
"https://www.googleapis.com/auth/drive",
null
);
2. Create a Google Slides Template
A Google Slides template is a pre-designed set of slides that can be used as a starting point for creating a new presentation. In your template, be sure to wrap any text that you expect to modify inside of mustache/handlebars syntax. For example, {{TITLE1}}
Once your Google Slides template is saved, the presentation’s URL should look like https://docs.google.com/presentation/d/G1bb3r1$h/edit
Make note of the characters between /d/ and /edit as this will serve as the template’s presentationId.
Note: Inside the template, each image will be assigned an imageObjectId
3. Copy Template from Google Drive
In the following code, we are copying a Google Slides presentation file with the specified presentationId
and creating a new copy with a different name, name
. The drive
object is likely an instance of the Google Drive API client, and the files.copy()
method is being called to create the copy of the presentation file. The fields
parameter specifies the response fields to include in the API response, and in this case, only the id
field is being returned. The new copy of the presentation file is created with the specified name
as its title. The await
keyword is used to wait for the asynchronous operation to complete before moving on to the next line of code.
const drive = google.drive({version: "v3", "auth": authDrive});
const result = await drive.files.copy({
fileId: presentationId,
fields: 'id',
resource: {
name: name
}
4. Set Permissions
const drive = google.drive({version: "v3", "auth": authDrive});
const permissionIds = [];
const permissions = [
{
type: 'user',
role: 'writer',
emailAddress: 'USER_TO_GRANT_ACCESS_TO@gmail.com',
},
];
for (const permission of permissions) {
try {
const result = await drive.permissions.create({
resource: permission,
fileId: presentationId,
fields: 'id',
});
permissionIds.push(result.data.id);
} catch (err) {
console.error("Error: " + err);
}
}
This code is granting a user with the email address “USER_TO_GRANT_ACCESS_TO@gmail.com” the permission to write (edit) a Google Drive file with the ID “presentationId”. The code creates a new permission object with the given user email address and role, and then loops through each permission object to create a new permission for the file using the Google Drive API. The “permissionIds” array keeps track of the IDs of the newly created permissions.
5. ReplaceAllText with OpenAI API
We begin by importing the Configuration and OpenAIApi classes from the “openai” package and creating a new instance of the Configuration class with an API key stored in an environment variable. The API key is used for authentication when making requests to the OpenAI API.
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
Next, we are using the OpenAI API to generate a short text prompt completion. The createCompletion()
function is called to generate a completion based on the provided prompt
, which is a string that serves as a starting point for the AI-generated text. The parameters passed to this function include the name of the OpenAI language model to be used (text-davinci-003
), the temperature
(which controls the level of randomness and creativity in the generated text), and the max_tokens
(which limits the length of the generated text). Once the API call returns a response, the first choice is selected and any leading or trailing whitespace is trimmed before assigning the generated text to the inspiration
variable.
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: "YOUR_PROMPT_GOES_HERE",
temperature: 0,
max_tokens: 10,
});
let inspiration = response.data.choices[0].text.trim();
Finally, we are creating a requests array which contains a replaceAllText object. The replaceAllText object specifies that the text in a document containing the string “{{PARAGRAPH}}” should be replaced with the string stored in the variable “inspiration”. The replaceText property of the replaceAllText object contains the new string to replace the old one, and the containsText property specifies the text to be replaced by using the text property containing the string “{{PARAGRAPH}}”.
This step can be repeatable multiple times for each text replacement and simply added to the requests
collection.
const requests = [{
replaceAllText: {
replaceText: inspiration,
containsText: {
text: '{{INSPIRATIONAL QUOTE}}'
}
}
}];
6. ReplaceImage with Midjourney
Prerequisite: Create an image using Midjourney and save it to a publicly accessible URL, which will set to
imgUrl
.
This code is creating a list of requests to be sent to the Google Slides API to replace an image on a slide with a new image from a specified URL. The requests
variable is an array that contains a single object representing the request. The replaceImage
property of this object specifies the type of request (replacing an image) and includes several parameters: imageObjectId
, which is the ID of the image to be replaced; imageReplaceMethod
, which specifies how to fit the new image into the original image's space; and url
, which is the URL of the new image.
This step can be repeatable multiple times for each image replacement and simply added to the requests
collection.
const requests = [{
replaceImage: {
"imageObjectId": "g2015e0649b0_0_52",
"imageReplaceMethod": "CENTER_INSIDE",
"url": imgUrl
}
}];
7. Batch Updates
Using the Google Slides API we can send a batch update request to the specified presentation. The request is to modify the presentation with the contents of the specified resource, which includes a list of individual update requests to apply to the presentation. The updates in this case are defined by the requests
array, which is passed as part of the resource object.
const presentation = await slides.presentations.batchUpdate({
presentationId: presentationId,
resource: { requests: requests }
});
Once completed, we can access the presentation URL:
presentationUrl: "https://docs.google.com/presentation/d/" + presentationId + "/edit"
Conclusion
Upon opening the slides, you should now see your OpenAI text, Midjourney images, and any other creative changes that you’ve applied to the template.