我希望创建一个服务器应用程序,该应用程序检查所述服务器上的文件夹并自动上传已放入所述文件夹的任何视频文件。服务器是远程的,不会发生人工交互。
在阅读了Youtube的API v3指南后,我得出的结论是,我需要一个"服务帐户"来上传这些视频,因为应用程序将不断监控这个文件夹。我的问题是:是否有可能使用服务帐户上传视频,然后将视频放在我的个人youtube帐户下?
如果这实际上是可能的;我已经创建了以下代码,但遇到了401未授权(无效令牌)错误。
我有以下可编译的源代码;我试着让它尽可能的小:
package PACKAGE;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.googleapis.media.MediaHttpUploader;
import com.google.api.client.googleapis.media.MediaHttpUploaderProgressListener;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.YouTubeScopes;
import com.google.api.services.youtube.model.PlaylistItem;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoSnippet;
import com.google.api.services.youtube.model.VideoStatus;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
public class BigQueryTestApp {
private static final String VIDEO_FILE_FORMAT = "video/*";
private static final String SAMPLE_VIDEO_FILENAME = "sample_video.mp4";
public static void main(String[] args) throws IOException, InterruptedException, GeneralSecurityException {
final HttpTransport TRANSPORT = new NetHttpTransport();
final JsonFactory JSON_FACTORY = new JacksonFactory();
File privateKeyFile = new File("privatekey.p12");
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXX@developer.gserviceaccount.com")
.setServiceAccountScopes(YouTubeScopes.all())
.setServiceAccountPrivateKeyFromP12File(privateKeyFile)
.build();
try
{
YouTube youtube = new YouTube.Builder(TRANSPORT, JSON_FACTORY, credential).setApplicationName("CHANGE_IT").build();
Video videoObjectDefiningMetadata = new Video();
VideoStatus status = new VideoStatus();
status.setPrivacyStatus("unlisted");
videoObjectDefiningMetadata.setStatus(status);
VideoSnippet snippet = new VideoSnippet();
Calendar cal = Calendar.getInstance();
snippet.setTitle("Test Upload via Java on " + cal.getTime());
snippet.setDescription(
"Video uploaded via YouTube Data API V3 using the Java library " + "on " + cal.getTime());
List<String> tags = new ArrayList<String>();
tags.add("test");
tags.add("example");
tags.add("java");
tags.add("YouTube Data API V3");
tags.add("erase me");
snippet.setTags(tags);
videoObjectDefiningMetadata.setSnippet(snippet);
InputStreamContent mediaContent = new InputStreamContent(VIDEO_FILE_FORMAT,
BigQueryTestApp.class.getResourceAsStream(SAMPLE_VIDEO_FILENAME));
YouTube.Videos.Insert videoInsert = youtube.videos().insert("snippet,statistics,status", videoObjectDefiningMetadata, mediaContent);
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();//thumbnailSet.getMediaHttpUploader();
uploader.setDirectUploadEnabled(false);
MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() {
public void progressChanged(MediaHttpUploader uploader) throws IOException
{
switch (uploader.getUploadState())
{
case INITIATION_STARTED:
System.out.println("Initiation Started");
break;
case INITIATION_COMPLETE:
System.out.println("Initiation Completed");
break;
case MEDIA_IN_PROGRESS:
System.out.println("Upload in progress");
System.out.println("Upload percentage: " + uploader.getProgress());
break;
case MEDIA_COMPLETE:
System.out.println("Upload Completed!");
break;
case NOT_STARTED:
System.out.println("Upload Not Started!");
break;
}
}
};
uploader.setProgressListener(progressListener);
// Call the API and upload the video.
Video returnedVideo = videoInsert.execute();
// Print data about the newly inserted video from the API response.
System.out.println("n================== Returned Video ==================n");
System.out.println(" - Id: " + returnedVideo.getId());
System.out.println(" - Title: " + returnedVideo.getSnippet().getTitle());
System.out.println(" - Tags: " + returnedVideo.getSnippet().getTags());
System.out.println(" - Privacy Status: " + returnedVideo.getStatus().getPrivacyStatus());
System.out.println(" - Video Count: " + returnedVideo.getStatistics().getViewCount());
}
catch (GoogleJsonResponseException e) {
System.out.println(e.getMessage());
System.out.println("Headers: "+e.getHeaders().toString());
}
最后,我读了很多关于服务账户的故事。一些人说它们与Youtube兼容,另一些人说它们不兼容。这让我很困惑,我在stackoverflow上发现了更多的问题,这些问题并没有明确地说明它是否可能。
YouTube不支持服务帐户,他们也没有计划:
https://code.google.com/p/gdata-issues/issues/detail?id=5370你的一个选择,然后,将你的应用程序设置为初始oAuth流(你与用户交互一次启动),然后作为该流的一部分,你将被颁发临时访问令牌和刷新令牌。刷新令牌可以用来获得更多的访问令牌,而不必再次运行oAuth流,刷新令牌不会自行过期(但是可以手动撤销)。所以你的应用程序可以存储你的刷新令牌,监控你的文件夹,然后在需要上传新视频时自己获得访问令牌。请看这个链接:
https://developers.google.com/youtube/v3/guides/moving_to_oauth独立
(注意它特别提到了一个守护进程的想法,该守护进程监视目录以上传新视频)