If you have N
accounts and want to upload videos on each of them, then you'll have to run to successful completion N
OAuth 2 authorization/authentication flows.
For each of these N
OAuth flows, upon completing each one successfully, you'll have to make persistent the obtained credentials data to a separate file within your computer local storage.
This could well be conceived as an initialization step of your app (although, at any later stage, you may well repeat it for any additional channel that you need your app be aware of). Your code would look like:
# run an OAuth flow; then obtain credentials data
# relative to the channel the app's user had chosen
# during that OAuth flow
from google_auth_oauthlib.flow import InstalledAppFlow
scopes = ['https://www.googleapis.com/auth/youtube']
flow = InstalledAppFlow.from_client_secrets_file(
client_secret_file, scopes)
cred = flow.run_console()
# build an YouTube service object such that to
# be able to retrieve the ID of the channel that
# the app's user had chosen during the OAuth flow
from googleapiclient.discovery import build
youtube = build('youtube', 'v3', credentials = cred)
response = youtube.channels().list(
part = 'id',
mine = True
).execute()
channel_id = response['items'][0]['id']
# save the credentials data to a JSON text file
cred_file = f"/path/to/credentials/data/dir/{channel_id}.json"
with open(cred_file, 'w', encoding = 'UTF-8') as json_file:
json_file.write(cred.to_json())
Above, client_secret_file
is the full path to the file containing your app's client secret JSON file that you've obtained from Google Developers Console.
Subsequently, each time you'll want to upload a video, you'll have to choose from within the app to which channel to upload that video. From the perspective of the logic of your program that would imply the following thing -- say you've chosen the channel of which ID is channel_id
: do read in the credentials data file associated to channel_id
for to pass its content to your YouTube service object youtube
constructed as shown below:
# read in the credentials data associated to
# the channel identified by its ID 'channel_id'
from google.oauth2.credentials import Credentials
cred_file = f"/path/to/credentials/data/dir/{channel_id}.json"
cred = Credentials.from_authorized_user_file(cred_file)
# the access token need be refreshed when
# the previously saved one expired already
from google.auth.transport.requests import Request
assert cred and cred.valid and cred.refresh_token
if cred.expired:
cred.refresh(Request())
# save credentials data upon it got refreshed
with open(cred_file, 'w', encoding = 'UTF-8') as json_file:
json_file.write(cred.to_json())
# construct an YouTube service object through
# which any API invocations are authorized on
# behalf of the channel with ID 'channel_id'
from googleapiclient.discovery import build
youtube = build('youtube', 'v3', credentials = cred)
Upon running this code, the YouTube service object youtube
will be initialized such a way that each an every API endpoint call that is issued through this object will accomplish an authorized request on behalf of the channel identified by channel_id
.
An important note: you need to have installed the package Google Authentication Library for Python, google-auth
, version >= 1.21.3 (google-auth
v1.3.0 introduced Credentials.from_authorized_user_file
, v1.8.0 introduced Credentials.to_json
and v1.21.3 fixed this latter function w.r.t. its class' expiry
member), for the credentials object cred
to be saved to and loaded from JSON text files.
Also an important note: the code above is simplified as much as possible. Error conditions are not handled at all. For example, the code above does not handle the error situation when cred_file
already exists at the time of writing out a new credentials data file or when cred_file
does not exist at the time of reading in credentials data that's supposed to already exist.