【Dart/Flutter】twitter_api_v2でメディアファイルを簡単にアップロードする方法
twitter_api_v2でメディアファイルを簡単にアップロードする方法
概要
Twitterで面白い画像や動画を共有するのは楽しいですよね。
twitter_api_v2で、このメディアファイルを簡単にアップロードできる機能をサポートしましたので、この記事ではその実装方法を紹介していきます。メディアをアップロードする際の難しい処理は全てカプセル化され、とても簡単に扱えるように設計・実装されていますのでぜひ使ってみてください。
ただし、公式のTwitter API v2.0ではまだv2エンドポイントとしてメディアのアップロードをサポートしておらず、twitter_api_v2では例外的にv1.1エンドポイントを使用しています。
そのため、将来的に公式でv2エンドポイントとしてメディアのアップロードがサポートされた場合には、引数の変更やレスポンス情報に変更が加わる可能性がある点に注意してください。
twitter_api_v2とは
twitter_api_v2とは、DartとFlutterで使用できるTwitter API v2.0をラッピングしたライブラリです。全てのエンドポイントやリクエストパラメータをサポートしているだけではなく、直感的なインターフェースや自動リトライなど、DartとFlutterでTwitter API v2.0を使用した開発を強力にサポートします。
このライブラリについては以前からいくつか記事を書いていますので、以下のリンクを参考にしてください。
ライブラリのインストール
まずは、DartまたはFlutterでお馴染みの以下のコマンドを実行してライブラリをインストールします。
Dartの場合:
dart pub add twitter_api_v2
Flutterの場合:
flutter pub add twitter_api_v2
また、必要に応じて以下のコマンドを実行しましょう。
Dartの場合:
dart pub get
Flutterの場合:
flutter pub get
メディアをアップロードする際の選択肢
さて、ここまでの工程でtwitter_api_v2のインストールが完了しました。
twitter_api_v2を使用してメディアをアップロードするためには、用途に合わせて以下の2つの選択肢があります。
メソッド名 | 説明 |
---|---|
uploadImage | 容量が5MBまでの画像とGIF画像のみをアップロードできます。ただし、公式のリファレンスにも記載されているとおり、容量の少ない画像ファイルのアップロードについても下記のuploadMediaを使用することが好ましいです。 |
uploadMedia | 大容量の画像、GIF画像、動画をアップロードできます。容量が大きいメディアファイルについては内部の処理で適切な容量にファイルを分割し、その分割したメディアファイルを安全にアップロードします。また、容量が大きいファイルについてはアップロードが完了するまでに時間がかかるため、定期的にTwitterのサーバーに対してポーリングを行い、アップロードのステータスを簡単に確認できる仕様もサポートしています。 |
上記の2つのメソッドについて順番に説明していきます。
uploadImageから画像をアップロード
先に紹介したように、uploadImageからは5MBまでの画像とGIF画像をアップロードできます。使い方はとても簡単で、uploadImageにアップロードしたい画像ファイルを表すFileオブジェクトを渡すだけです。
import 'dart:io';
import 'package:twitter_api_v2/twitter_api_v2.dart';
Future<void> main() async {
final twitter = TwitterApi(
// メディアのアップロードはv1.1エンドポイントを使用しているため、
// OAuth 2.0 のアクセストークンは必要ありません。
bearerToken: 'NO_NEED_OAUTH2_AUTHORIZATION',
// その代わりに、OAuth 1.0a のアクセストークンは指定が必須です。
oauthTokens: OAuthTokens(
consumerKey: 'YOUR_CONSUMER_KEY',
consumerSecret: 'YOUR_CONSUMER_SECRET',
accessToken: 'YOUR_ACCESS_TOKEN',
accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET',
),
);
try {
// uploadImageメソッドにアップロードしたい画像ファイルのオブジェクトを渡してください。
//
// アップロードが完了するとアップロードファイルの情報が格納されたオブジェクトが返却されます。
final uploadedMedia = await twitter.media.uploadImage(
file: File.fromUri(
Uri.file('funny_image.png'),
),
);
print(uploadedMedia);
} on TwitterUploadException catch (e) {
print(e);
}
}
このサンプルコードを実行すると以下の出力を得られます。
TwitterResponse(rateLimit: RateLimit(limitCount: 415, remainingCount: 414, resetAt: 2022-10-31 10:41:12.000), data: UploadedMediaData(id: 1586880937216061440, expiresAt: 2022-11-01 09:41:13.427949), includes: null, meta: null)
TwitterResponse
のdata
フィールドにアップロードしたメディアのIDがありますので、このIDを使用してツイートをすることで画像つきのツイートを作成することができます。
上記のとおり使い方はとても簡単ですが、上記のサンプルコードのコメントにもあるように、メディアのアップロードはv1.1エンドポイントを使用しているため、OAuth 2.0のトークンではなく、OAuth 1.0aのトークンが必須になりますので注意してください。
uploadMediaから画像をアップロード
さて、先に紹介したuploadImageを使用することでも画像ファイルのアップロードは可能ですが、このメソッドからは大容量の画像ファイルや動画ファイルをアップロードすることはできません。
これらの容量の大きいメディアファイルをアップロードするためには、uploadMediaを使用する必要があります。ただ、メソッドの使い方はuploadImageと基本的には同じであり、アップロードしたい画像や動画を表すFileオブジェクトを引数として渡すだけです。
import 'dart:io';
import 'package:twitter_api_v2/twitter_api_v2.dart';
Future<void> main() async {
final twitter = TwitterApi(
// メディアのアップロードはv1.1エンドポイントを使用しているため、
// OAuth 2.0 のアクセストークンは必要ありません。
bearerToken: 'NO_NEED_OAUTH2_AUTHORIZATION',
// その代わりに、OAuth 1.0a のアクセストークンは指定が必須です。
oauthTokens: OAuthTokens(
consumerKey: 'YOUR_CONSUMER_KEY',
consumerSecret: 'YOUR_CONSUMER_SECRET',
accessToken: 'YOUR_ACCESS_TOKEN',
accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET',
),
);
try {
final uploadedMedia = await twitter.media.uploadMedia(
file: File.fromUri(
Uri.file('funny_video.mp4'),
),
// アップロードの完了までに時間がかかる場合、
// onProgressコールバックからアップロードの進捗を確認できます。
//
// ステータスは以下の順番で遷移します。
// 1. UploadState.preparing
// 2. UploadState.inProgress
// 3. UploadState.completed
onProgress: (event) {
switch (event.state) {
case UploadState.preparing:
print('Upload is preparing...');
break;
case UploadState.inProgress:
print('${event.progress}% completed...');
break;
case UploadState.completed:
print('Upload has completed!');
break;
}
},
// メディアのアップロードに失敗した場合に呼ばれるコールバック関数です。
onFailed: (error) => print('Upload failed. Due to "${error.message}"'),
);
print(uploadedMedia);
} on TwitterUploadException catch (e) {
print(e);
}
}
上記のサンプルコードを実行すると以下の出力を得られます。
TwitterResponse(rateLimit: RateLimit(limitCount: 200, remainingCount: 198, resetAt: 2022-10-31 11:25:41.000), data: UploadedMediaData(id: 1586893070288945152, expiresAt: 2022-11-01 10:32:13.449770), includes: null, meta: null)
また、uploadImageとは異なる点として、onProgress
コールバックを使用することで、メディアアップロードの進捗状況を確認することができます。例えば、上記のサンプルコードから容量の大きい動画ファイルをアップロードした場合には、アップロードの進捗を以下のように得られます。これはFlutterアプリで動画ファイルのアップロード状況をポップアップ等でユーザーに示す際に便利です。
Upload is preparing...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
5% completed...
20% completed...
20% completed...
20% completed...
46% completed...
73% completed...
Upload has completed!
このアップロードの進捗について、ステータスは以下のとおりに遷移します。
順 | ステータス | 説明 |
---|---|---|
1 | UploadState.preparing | アップロードが開始したことを示します。onProgress コールバックが指定された場合には、アップロード処理の開始時に必ず発生します。 |
2 | UploadState.inProgress | アップロードが進行中であることを示します。アップロードの完了までに時間を要する場合には、Twitterのサーバーに対してポーリングを行うたたびにこのステータスでのイベントが発生します。進捗状況はパーセントで表され、UploadEvent.progressから値を取得できます。ただし、容量が大きくなくTwitterサーバーに対する進捗状況のポーリングが不要な場合には、このイベントは発生せず次のUploadState.completed に遷移します。 |
3 | UploadState.completed | アップロードが正常に完了したことを示します。onProgress コールバックが指定された場合には、アップロード処理の完了時に必ず発生します。 |
さらに、onFailed
コールバック関数を指定することで、メディアのアップロードに失敗した際の情報を取得することができます。ただし、onFailed
コールバック関数を指定した場合でも、アップロード処理の失敗時にはTwitterUploadException
が投げられる点に注意してください。
また、uploadMediaではTwitterへメディアをアップロードする際に発生しがちな瑣末なエラーは発生しないように処理が設計されています。ただ、以下の場合には必ずTwitterUploadException
が投げられますので、実装時にはご注意ください。
- メディアファイルが破損している(外部システムからダウンロード途中等)。
- 動画ファイルの再生時間が2分20秒を超えている。
- Twitterでサポートされていないメディアフォーマット。
その他
アップロードしたメディアを使用してツイート
アップロードしたメディアデータは以下の方法で簡単にツイートに添付することができます。
import 'dart:io';
import 'package:twitter_api_v2/twitter_api_v2.dart';
Future<void> main() async {
final twitter = TwitterApi(
bearerToken: 'YOUR_BEARER_TOKEN',
oauthTokens: OAuthTokens(
consumerKey: 'YOUR_CONSUMER_KEY',
consumerSecret: 'YOUR_CONSUMER_SECRET',
accessToken: 'YOUR_ACCESS_TOKEN',
accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET',
),
);
try {
final uploadedMedia = await twitter.media.uploadMedia(
file: File.fromUri(
Uri.file('funny_movie.mp4'),
),
onProgress: (event) {
switch (event.state) {
case UploadState.preparing:
print('Upload is preparing...');
break;
case UploadState.inProgress:
print('${event.progress}% completed...');
break;
case UploadState.completed:
print('Upload has completed!');
break;
}
},
onFailed: (error) => print('Upload failed. Due to "${error.message}"'),
);
await twitter.tweets.createTweet(
text: 'Tweet with media!',
media: TweetMediaParam(
mediaIds: [
uploadedMedia.data.id,
],
),
);
} on TwitterUploadException catch (e) {
print(e);
}
}
twitter_api_v2を使用してメディアを添付したツイートの作成方法は過去に以下の記事を書いていますので参考にしてください。
アップロードしたメディアの使用可能ユーザーを追加
uploadImageとuploadMediaを使用してアップロードしたメディアは、基本的にアップロードを実施した認証ユーザーだけがツイート等で使用することができます。
しかし、uploadImageとuploadMediaの引数であるadditionalOwners
にユーザーIDの配列を渡すことで、アップロードしたメディアファイルを使用できるユーザーを追加することができます。
import 'dart:io';
import 'package:twitter_api_v2/twitter_api_v2.dart';
Future<void> main() async {
final twitter = TwitterApi(
// メディアのアップロードはv1.1エンドポイントを使用しているため、
// OAuth 2.0 のアクセストークンは必要ありません。
bearerToken: 'NO_NEED_OAUTH2_AUTHORIZATION',
// その代わりに、OAuth 1.0a のアクセストークンは指定が必須です。
oauthTokens: OAuthTokens(
consumerKey: 'YOUR_CONSUMER_KEY',
consumerSecret: 'YOUR_CONSUMER_SECRET',
accessToken: 'YOUR_ACCESS_TOKEN',
accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET',
),
);
try {
final uploadedMedia = await twitter.media.uploadMedia(
file: File.fromUri(
Uri.file('funny_video.mp4'),
),
// メディアファイルの使用可能ユーザーを追加。
additionalOwners: ['11111', '22222'],
);
print(uploadedMedia);
} on TwitterUploadException catch (e) {
print(e);
}
}
アップロードするメディアにAltテキストを追加
Twitterではアップロードしたメディアに280文字を超える説明文をAltテキストとして登録することができます。
twitter_api_v2でもこの仕様をサポートしており、uploadImageとuploadMediaの引数であるaltText
に任意の文字列を指定することで、メディアのアップロード時にAltテキストを登録可能です。
import 'dart:io';
import 'package:twitter_api_v2/twitter_api_v2.dart';
Future<void> main() async {
final twitter = TwitterApi(
bearerToken: 'NO_NEED_OAUTH2_AUTHORIZATION',
oauthTokens: OAuthTokens(
consumerKey: 'YOUR_CONSUMER_KEY',
consumerSecret: 'YOUR_CONSUMER_SECRET',
accessToken: 'YOUR_ACCESS_TOKEN',
accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET',
),
);
try {
final uploadedMedia = await twitter.media.uploadMedia(
file: File.fromUri(
Uri.file('funny_movie.mp4'),
),
// Altテキストを登録するためにはこの引数を指定してください。
altText: 'This is alt text!',
);
print(uploadedMedia);
} on TwitterUploadException catch (e) {
print(e);
}
}
まとめ
簡単な説明でしたが、以上がtwitter_api_v2でメディアをアップロードする方法になります。
uploadImageよりもuploadMediaのエンドポイントほうが好ましいと公式のリファレンスにも書かれていますが、これはケースバイケースだと思いますので状況に応じて好きなほうを使用していただいて構いません。なにより、容量の少ない画像ファイルであれば、余計な処理が実行されないだけuploadImageのほうが圧倒的に高速に動作します。
また、twitter_api_v2は他にも多くのエンドポイントをサポートしていますので、Twitter API v2.0を使用したアプリケーションを作成する際にはぜひ使用してください。
貢献者の募集
twitter_api_v2はオープンソースですのでどのような方でも開発に貢献することができます。開発リポジトリの公用語は英語にしていますが、日本人の方々も大歓迎ですのでお気軽にIssue
やPull Request
を作成してください。
また、このライブラリが役に立った場合にGitHub の開発リポジトリにスターを付けることや、Pub.dev でいいねを付けることもよろしくお願いします!これはtwitter_api_v2の開発コミュニティを活性化するためにとても大きな意味があります。
もしなにか疑問がある場合は開発リポジトリのディスカッションにでもスレッドを立てていただければと思います。
スポンサーの募集
オープンソース開発をサポートしてくださるスポンサーを募集しています。少額($1)からの寄付も可能ですので、以下のリンクから是非ご支援ください。
また、この記事にバッジを贈っていただくことでも支援は可能です。
Discussion