通过 android 在 YouTube 上直播时处于非活动状态
Inactive stream when going live on youtube through android
我可以通过 Youtube 创建活动 api。活动正在我的 Youtube 页面 "events tab"(即将推出的类别)中显示。
但是当我开始流式传输时 returns 错误 403(流处于非活动状态)。我想在每次直播时创建一个新的广播事件。
任何帮助将不胜感激。这是我的代码....
这是在 AsyncTask
:
YouTube youtube = new YouTube.Builder(transport, jsonFactory,
credential).setApplicationName(APP_NAME).build();
YouTubeApi.createLiveEvent(youtube, "event description", "event name");
在方法中 YoutubeApi.createLiveEvent(...)
:
public static void createLiveEvent(YouTube youtube, String description,
String name) {
try {
LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
broadcastSnippet.setTitle(name);
broadcastSnippet.setScheduledStartTime(new DateTime(new Date()));
LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
MonitorStreamInfo monitorStream = new MonitorStreamInfo();
monitorStream.setEnableMonitorStream(false);
contentDetails.setMonitorStream(monitorStream);
// Create LiveBroadcastStatus with privacy status.
LiveBroadcastStatus status = new LiveBroadcastStatus();
status.setPrivacyStatus("public");
LiveBroadcast broadcast = new LiveBroadcast();
broadcast.setKind("youtube#liveBroadcast");
broadcast.setSnippet(broadcastSnippet);
broadcast.setStatus(status);
broadcast.setContentDetails(contentDetails);
// Create the insert request
YouTube.LiveBroadcasts.Insert liveBroadcastInsert = youtube
.liveBroadcasts().insert("snippet,status,contentDetails",
broadcast);
// Request is executed and inserted broadcast is returned
LiveBroadcast returnedBroadcast = liveBroadcastInsert.execute();
// Create a snippet with title.
LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
streamSnippet.setTitle(name);
// Create content distribution network with format and ingestion
// type.
CdnSettings cdn = new CdnSettings();
cdn.setFormat("240p");
cdn.setIngestionType("rtmp");
LiveStream stream = new LiveStream();
stream.setKind("youtube#liveStream");
stream.setSnippet(streamSnippet);
stream.setCdn(cdn);
// Create the insert request
YouTube.LiveStreams.Insert liveStreamInsert = youtube.liveStreams()
.insert("snippet,cdn", stream);
// Request is executed and inserted stream is returned
LiveStream returnedStream = liveStreamInsert.execute();
// Create the bind request
YouTube.LiveBroadcasts.Bind liveBroadcastBind = youtube
.liveBroadcasts().bind(returnedBroadcast.getId(),
"id,contentDetails");
// Set stream id to bind
liveBroadcastBind.setStreamId(returnedStream.getId());
// Request is executed and bound broadcast is returned
liveBroadcastBind.execute();
} catch (GoogleJsonResponseException e) {
System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
e.printStackTrace();
} catch (Throwable t) {
System.err.println("Throwable: " + t.getStackTrace());
t.printStackTrace();
}
}
这是我启动事件流的代码:
public static void startEvent(YouTube youtube, String broadcastId) // broadcast id is same(checked)
throws IOException {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(APP_NAME, "", e);
}
YouTube.LiveStreams.List liveBroadcastRequest = youtube
.liveStreams().list("id,snippet,status");
// liveBroadcastRequest.setMine(true);
liveBroadcastRequest.setId(broadcastId); // setBroadcastStatus("upcoming");
// List request is executed and list of broadcasts are returned
LiveStreamListResponse returnedListResponse = liveBroadcastRequest.execute();
List<LiveStream> returnedList = returnedListResponse.getItems();
Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", broadcastId, "status");
transitionRequest.execute();
}
我收到的异常日志:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code": 403,
"errors": [
{
"domain": "youtube.liveBroadcast",
"message": "Stream is inactive",
"reason": "errorStreamInactive",
"extendedHelp": "https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition"
}
],
"message": "Stream is inactive"
}
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at net.ossrs.yasea.demo.utils.YouTubeApi.startEvent(YouTubeApi.java:236)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:160)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:144)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818
您需要等待流状态切换到active
。所以你必须存储你的流 ID 和你的广播 ID 等待这个状态。
可以使用 TimerTask
或 ScheduledExecutorService
来完成检查:
mScheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
// check every 2 seconds the stream status
mScheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if (mStreamId != null) {
checkStreamStatus();
}
} catch (IOException e) {
Log.e(TAG, null, e);
}
}
}, 0, 2, TimeUnit.SECONDS);
checkStreamStatus
方法检查流状态,如果需要它还可以检查流健康(健康状态"GOOD"
):
public void checkStreamStatus() throws IOException {
YouTube.LiveStreams.List livestreamRequest = youtube.liveStreams().list("status");
livestreamRequest.setId(mStreamId);
LiveStreamListResponse returnedListResponse = livestreamRequest.execute();
List < LiveStream > returnedList = returnedListResponse.getItems();
if (returnedList.size() == 1) {
LiveStream stream = returnedList.get(0);
Log.v(TAG, "the current stream status is : " + stream.getStatus().getStreamStatus());
if (stream.getStatus().getStreamStatus().equals("active")) {
Log.v(TAG, "start broadcasting now");
startEvent();
mScheduleTaskExecutor.shutdownNow();
}
}
}
这是一个完整的例子:
public class YoutubeTask extends AsyncTask < Void, Void, String > {
private final static String TAG = YoutubeTask.class.getSimpleName();
private ScheduledExecutorService mScheduleTaskExecutor;
private String mStreamId;
private String mBroadcastId;
private static YouTube youtube;
@Override
protected String doInBackground(Void...params) {
mScheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
// Authorize the request.
Credential credential = new GoogleCredential().setAccessToken("...");
// This object is used to make YouTube Data API requests.
youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
.setApplicationName("youtube-cmdline-createbroadcast-sample").build();
createLiveEvent(youtube, "event name");
// check every 2 seconds the stream status
mScheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if (mStreamId != null) {
checkStreamStatus();
}
} catch (IOException e) {
Log.e(TAG, null, e);
}
}
}, 0, 2, TimeUnit.SECONDS);
return null;
}
public void createLiveEvent(YouTube youtube, String name) {
try {
LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
broadcastSnippet.setTitle(name);
broadcastSnippet.setScheduledStartTime(new DateTime(new Date()));
LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
MonitorStreamInfo monitorStream = new MonitorStreamInfo();
monitorStream.setEnableMonitorStream(false);
contentDetails.setMonitorStream(monitorStream);
LiveBroadcastStatus status = new LiveBroadcastStatus();
status.setPrivacyStatus("public");
LiveBroadcast broadcast = new LiveBroadcast();
broadcast.setKind("youtube#liveBroadcast");
broadcast.setSnippet(broadcastSnippet);
broadcast.setStatus(status);
broadcast.setContentDetails(contentDetails);
YouTube.LiveBroadcasts.Insert liveBroadcastInsert = youtube
.liveBroadcasts().insert("snippet,status,contentDetails",
broadcast);
LiveBroadcast returnedBroadcast = liveBroadcastInsert.execute();
LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
streamSnippet.setTitle(name);
CdnSettings cdn = new CdnSettings();
cdn.setFormat("240p");
cdn.setIngestionType("rtmp");
LiveStream stream = new LiveStream();
stream.setKind("youtube#liveStream");
stream.setSnippet(streamSnippet);
stream.setCdn(cdn);
// Create the insert request
YouTube.LiveStreams.Insert liveStreamInsert = youtube.liveStreams().insert("snippet,cdn", stream);
// Request is executed and inserted stream is returned
LiveStream returnedStream = liveStreamInsert.execute();
// Create the bind request
YouTube.LiveBroadcasts.Bind liveBroadcastBind = youtube.liveBroadcasts().bind(returnedBroadcast.getId(),
"id,contentDetails");
// Set stream id to bind
liveBroadcastBind.setStreamId(returnedStream.getId());
// Request is executed and bound broadcast is returned
liveBroadcastBind.execute();
// store stream Id & broadcast Id
mStreamId = returnedStream.getId();
mBroadcastId = returnedBroadcast.getId();
} catch (GoogleJsonResponseException e) {
Log.e(TAG, null, e);
} catch (IOException e) {
Log.e(TAG, null, e);
} catch (Throwable t) {
Log.e(TAG, null, t);
}
}
public void checkStreamStatus() throws IOException {
YouTube.LiveStreams.List livestreamRequest = youtube.liveStreams().list("status");
livestreamRequest.setId(mStreamId);
LiveStreamListResponse returnedListResponse = livestreamRequest.execute();
List < LiveStream > returnedList = returnedListResponse.getItems();
if (returnedList.size() == 1) {
LiveStream stream = returnedList.get(0);
Log.v(TAG, "the current stream status is : " + stream.getStatus().getStreamStatus());
if (stream.getStatus().getStreamStatus().equals("active")) {
Log.v(TAG, "start broadcasting now");
startEvent();
mScheduleTaskExecutor.shutdownNow();
}
}
}
public void startEvent() throws IOException {
YouTube.LiveBroadcasts.Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", mBroadcastId, "status");
transitionRequest.execute();
}
}
使用 new YoutubeTask().execute();
启动此示例
您可以使用取自 oauth playground with scope https://www.googleapis.com/auth/youtube
. Also for testing the stream, I recommend to use the Android app RTMP Camera 的访问令牌直接对此进行测试,以测试到 Youtube 的摄像头流,您可以在其中直接输入流名称 XXXX-XXXX-XXXX-XXXX
几天前我遇到了类似的问题...这就是我所做的...
要记住的要点:a) 您可能会在 API 中收到与 youtube 活动门户不同的 RTMP url。
b) 无论您是否能够 "go live",您都可能在调用广播转换到状态 "Live" 时收到 403 错误。
现在出现错误 403(流不活动):
确保在调用 "transition on broadcast" 之前将 frames/data 发送到 YouTube。
现在在线程暂停几秒的 diff 线程上调用 "Broadcast.transition"(将数据发送到 youtube 可能需要一些时间)。
例如:
public static void startEvent(final YouTube youtube, final String broadcastId)
抛出 IOException {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Log.e(APP_NAME, "", e);
}
Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", broadcastId, "status");
transitionRequest.execute();
}
希望对您有所帮助....
我可以通过 Youtube 创建活动 api。活动正在我的 Youtube 页面 "events tab"(即将推出的类别)中显示。 但是当我开始流式传输时 returns 错误 403(流处于非活动状态)。我想在每次直播时创建一个新的广播事件。 任何帮助将不胜感激。这是我的代码....
这是在 AsyncTask
:
YouTube youtube = new YouTube.Builder(transport, jsonFactory,
credential).setApplicationName(APP_NAME).build();
YouTubeApi.createLiveEvent(youtube, "event description", "event name");
在方法中 YoutubeApi.createLiveEvent(...)
:
public static void createLiveEvent(YouTube youtube, String description,
String name) {
try {
LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
broadcastSnippet.setTitle(name);
broadcastSnippet.setScheduledStartTime(new DateTime(new Date()));
LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
MonitorStreamInfo monitorStream = new MonitorStreamInfo();
monitorStream.setEnableMonitorStream(false);
contentDetails.setMonitorStream(monitorStream);
// Create LiveBroadcastStatus with privacy status.
LiveBroadcastStatus status = new LiveBroadcastStatus();
status.setPrivacyStatus("public");
LiveBroadcast broadcast = new LiveBroadcast();
broadcast.setKind("youtube#liveBroadcast");
broadcast.setSnippet(broadcastSnippet);
broadcast.setStatus(status);
broadcast.setContentDetails(contentDetails);
// Create the insert request
YouTube.LiveBroadcasts.Insert liveBroadcastInsert = youtube
.liveBroadcasts().insert("snippet,status,contentDetails",
broadcast);
// Request is executed and inserted broadcast is returned
LiveBroadcast returnedBroadcast = liveBroadcastInsert.execute();
// Create a snippet with title.
LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
streamSnippet.setTitle(name);
// Create content distribution network with format and ingestion
// type.
CdnSettings cdn = new CdnSettings();
cdn.setFormat("240p");
cdn.setIngestionType("rtmp");
LiveStream stream = new LiveStream();
stream.setKind("youtube#liveStream");
stream.setSnippet(streamSnippet);
stream.setCdn(cdn);
// Create the insert request
YouTube.LiveStreams.Insert liveStreamInsert = youtube.liveStreams()
.insert("snippet,cdn", stream);
// Request is executed and inserted stream is returned
LiveStream returnedStream = liveStreamInsert.execute();
// Create the bind request
YouTube.LiveBroadcasts.Bind liveBroadcastBind = youtube
.liveBroadcasts().bind(returnedBroadcast.getId(),
"id,contentDetails");
// Set stream id to bind
liveBroadcastBind.setStreamId(returnedStream.getId());
// Request is executed and bound broadcast is returned
liveBroadcastBind.execute();
} catch (GoogleJsonResponseException e) {
System.err.println("GoogleJsonResponseException code: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
e.printStackTrace();
} catch (Throwable t) {
System.err.println("Throwable: " + t.getStackTrace());
t.printStackTrace();
}
}
这是我启动事件流的代码:
public static void startEvent(YouTube youtube, String broadcastId) // broadcast id is same(checked)
throws IOException {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(APP_NAME, "", e);
}
YouTube.LiveStreams.List liveBroadcastRequest = youtube
.liveStreams().list("id,snippet,status");
// liveBroadcastRequest.setMine(true);
liveBroadcastRequest.setId(broadcastId); // setBroadcastStatus("upcoming");
// List request is executed and list of broadcasts are returned
LiveStreamListResponse returnedListResponse = liveBroadcastRequest.execute();
List<LiveStream> returnedList = returnedListResponse.getItems();
Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", broadcastId, "status");
transitionRequest.execute();
}
我收到的异常日志:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code": 403,
"errors": [
{
"domain": "youtube.liveBroadcast",
"message": "Stream is inactive",
"reason": "errorStreamInactive",
"extendedHelp": "https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition"
}
],
"message": "Stream is inactive"
}
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at net.ossrs.yasea.demo.utils.YouTubeApi.startEvent(YouTubeApi.java:236)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:160)
at net.ossrs.yasea.demo.rtmp.YoutubeRTMPUrl$StartEventTask.doInBackground(YoutubeRTMPUrl.java:144)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818
您需要等待流状态切换到active
。所以你必须存储你的流 ID 和你的广播 ID 等待这个状态。
可以使用 TimerTask
或 ScheduledExecutorService
来完成检查:
mScheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
// check every 2 seconds the stream status
mScheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if (mStreamId != null) {
checkStreamStatus();
}
} catch (IOException e) {
Log.e(TAG, null, e);
}
}
}, 0, 2, TimeUnit.SECONDS);
checkStreamStatus
方法检查流状态,如果需要它还可以检查流健康(健康状态"GOOD"
):
public void checkStreamStatus() throws IOException {
YouTube.LiveStreams.List livestreamRequest = youtube.liveStreams().list("status");
livestreamRequest.setId(mStreamId);
LiveStreamListResponse returnedListResponse = livestreamRequest.execute();
List < LiveStream > returnedList = returnedListResponse.getItems();
if (returnedList.size() == 1) {
LiveStream stream = returnedList.get(0);
Log.v(TAG, "the current stream status is : " + stream.getStatus().getStreamStatus());
if (stream.getStatus().getStreamStatus().equals("active")) {
Log.v(TAG, "start broadcasting now");
startEvent();
mScheduleTaskExecutor.shutdownNow();
}
}
}
这是一个完整的例子:
public class YoutubeTask extends AsyncTask < Void, Void, String > {
private final static String TAG = YoutubeTask.class.getSimpleName();
private ScheduledExecutorService mScheduleTaskExecutor;
private String mStreamId;
private String mBroadcastId;
private static YouTube youtube;
@Override
protected String doInBackground(Void...params) {
mScheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
// Authorize the request.
Credential credential = new GoogleCredential().setAccessToken("...");
// This object is used to make YouTube Data API requests.
youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
.setApplicationName("youtube-cmdline-createbroadcast-sample").build();
createLiveEvent(youtube, "event name");
// check every 2 seconds the stream status
mScheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
if (mStreamId != null) {
checkStreamStatus();
}
} catch (IOException e) {
Log.e(TAG, null, e);
}
}
}, 0, 2, TimeUnit.SECONDS);
return null;
}
public void createLiveEvent(YouTube youtube, String name) {
try {
LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
broadcastSnippet.setTitle(name);
broadcastSnippet.setScheduledStartTime(new DateTime(new Date()));
LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
MonitorStreamInfo monitorStream = new MonitorStreamInfo();
monitorStream.setEnableMonitorStream(false);
contentDetails.setMonitorStream(monitorStream);
LiveBroadcastStatus status = new LiveBroadcastStatus();
status.setPrivacyStatus("public");
LiveBroadcast broadcast = new LiveBroadcast();
broadcast.setKind("youtube#liveBroadcast");
broadcast.setSnippet(broadcastSnippet);
broadcast.setStatus(status);
broadcast.setContentDetails(contentDetails);
YouTube.LiveBroadcasts.Insert liveBroadcastInsert = youtube
.liveBroadcasts().insert("snippet,status,contentDetails",
broadcast);
LiveBroadcast returnedBroadcast = liveBroadcastInsert.execute();
LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
streamSnippet.setTitle(name);
CdnSettings cdn = new CdnSettings();
cdn.setFormat("240p");
cdn.setIngestionType("rtmp");
LiveStream stream = new LiveStream();
stream.setKind("youtube#liveStream");
stream.setSnippet(streamSnippet);
stream.setCdn(cdn);
// Create the insert request
YouTube.LiveStreams.Insert liveStreamInsert = youtube.liveStreams().insert("snippet,cdn", stream);
// Request is executed and inserted stream is returned
LiveStream returnedStream = liveStreamInsert.execute();
// Create the bind request
YouTube.LiveBroadcasts.Bind liveBroadcastBind = youtube.liveBroadcasts().bind(returnedBroadcast.getId(),
"id,contentDetails");
// Set stream id to bind
liveBroadcastBind.setStreamId(returnedStream.getId());
// Request is executed and bound broadcast is returned
liveBroadcastBind.execute();
// store stream Id & broadcast Id
mStreamId = returnedStream.getId();
mBroadcastId = returnedBroadcast.getId();
} catch (GoogleJsonResponseException e) {
Log.e(TAG, null, e);
} catch (IOException e) {
Log.e(TAG, null, e);
} catch (Throwable t) {
Log.e(TAG, null, t);
}
}
public void checkStreamStatus() throws IOException {
YouTube.LiveStreams.List livestreamRequest = youtube.liveStreams().list("status");
livestreamRequest.setId(mStreamId);
LiveStreamListResponse returnedListResponse = livestreamRequest.execute();
List < LiveStream > returnedList = returnedListResponse.getItems();
if (returnedList.size() == 1) {
LiveStream stream = returnedList.get(0);
Log.v(TAG, "the current stream status is : " + stream.getStatus().getStreamStatus());
if (stream.getStatus().getStreamStatus().equals("active")) {
Log.v(TAG, "start broadcasting now");
startEvent();
mScheduleTaskExecutor.shutdownNow();
}
}
}
public void startEvent() throws IOException {
YouTube.LiveBroadcasts.Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", mBroadcastId, "status");
transitionRequest.execute();
}
}
使用 new YoutubeTask().execute();
您可以使用取自 oauth playground with scope https://www.googleapis.com/auth/youtube
. Also for testing the stream, I recommend to use the Android app RTMP Camera 的访问令牌直接对此进行测试,以测试到 Youtube 的摄像头流,您可以在其中直接输入流名称 XXXX-XXXX-XXXX-XXXX
几天前我遇到了类似的问题...这就是我所做的...
要记住的要点:a) 您可能会在 API 中收到与 youtube 活动门户不同的 RTMP url。
b) 无论您是否能够 "go live",您都可能在调用广播转换到状态 "Live" 时收到 403 错误。
现在出现错误 403(流不活动):
确保在调用 "transition on broadcast" 之前将 frames/data 发送到 YouTube。 现在在线程暂停几秒的 diff 线程上调用 "Broadcast.transition"(将数据发送到 youtube 可能需要一些时间)。
例如:
public static void startEvent(final YouTube youtube, final String broadcastId) 抛出 IOException {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Log.e(APP_NAME, "", e);
}
Transition transitionRequest = youtube.liveBroadcasts().transition(
"live", broadcastId, "status");
transitionRequest.execute();
}
希望对您有所帮助....