Skip to content

Commit

Permalink
优化直播开启逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
withsalt committed Nov 22, 2019
1 parent e58dac1 commit b410640
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 37 deletions.
35 changes: 21 additions & 14 deletions src/Bilibili/Api/LoginApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,33 @@ public static async Task<string> GetKeyAsync(User user)
/// <returns></returns>
public static async Task<string> GetInfoAsync(User user)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
try
{
if (user == null)
throw new ArgumentNullException(nameof(user));

QueryCollection queries;
QueryCollection queries;

queries = new QueryCollection {
queries = new QueryCollection {
{ "access_key", user.Data.AccessKey },
{ "ts", ApiUtils.GetTimeStamp().ToString() }
};
queries.AddRange(user.Data.Cookie.Split(';').Select(item =>
queries.AddRange(user.Data.Cookie.Split(';').Select(item =>
{
string[] pair;

pair = item.Split('=');
return new KeyValuePair<string, string>(pair[0], pair[1]);
}));
queries.AddRange(General);
queries.SortAndSign();
using HttpResponseMessage response = await user.Handler.SendAsync(HttpMethod.Get, OAUTH2_INFO_URL, queries, user.AppHeaders);
return await response.Content.ReadAsStringAsync();
}
catch
{
string[] pair;

pair = item.Split('=');
return new KeyValuePair<string, string>(pair[0], pair[1]);
}));
queries.AddRange(General);
queries.SortAndSign();
using HttpResponseMessage response = await user.Handler.SendAsync(HttpMethod.Get, OAUTH2_INFO_URL, queries, user.AppHeaders);
return await response.Content.ReadAsStringAsync();
return null;
}
}

/// <summary>
Expand Down
48 changes: 48 additions & 0 deletions src/BilibiliLiveTools/Common/NetworkTools.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Bilibili.Settings;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;

namespace BilibiliLiveTools.Common
{
public class NetworkTools
{
private static readonly List<string> _hosts = new List<string>()
{
"114.114.114.114",
"223.5.5.5",
"1.2.4.8"
};

/// <summary>
/// 通过Ping验证网络是否断开
/// </summary>
/// <returns></returns>
public static async Task<bool> NetworkCheck()
{
try
{
Ping ping = new Ping();
PingOptions options = new PingOptions
{
DontFragment = true
};
foreach (var item in _hosts)
{
PingReply reply = await ping.SendPingAsync(item, 1024);
if (reply.Status == IPStatus.Success)
{
return true;
}
}
return false;
}
catch(Exception ex)
{
return false;
}
}
}
}
104 changes: 81 additions & 23 deletions src/BilibiliLiveTools/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Bilibili;
using Bilibili.Api;
using Bilibili.Helper;
using Bilibili.Model.Live.LiveRoomStreamInfo;
using Bilibili.Model.Live.StartLiveInfo;
using Bilibili.Settings;
using BilibiliLiveTools.Common;
using BilibiliLiveTools.Model;
using System;
using System.Diagnostics;
Expand All @@ -16,11 +18,11 @@ namespace BilibiliLiveTools
{
class Program
{
private static Users _users;

static async Task Main(string[] args)
{
string usersFilePath;
Users users;

GlobalSettings.Logger = Logger.Instance;
if (!BitConverter.IsLittleEndian)
{
Expand All @@ -31,25 +33,41 @@ static async Task Main(string[] args)
try
{
GlobalSettings.LoadAll();
users = Users.FromJson(File.ReadAllText(usersFilePath));
_users = Users.FromJson(File.ReadAllText(usersFilePath));
if (_users == null || _users.Count == 0)
{
throw new Exception("Load user info failed.");
}
}
catch (Exception ex)
{
GlobalSettings.Logger.LogException(ex);
GlobalSettings.Logger.LogError($"缺失或无效配置文件,请检查是否添加\"{usersFilePath}\"");
return;
}
LoginApiExtensions.LoginDataUpdated += (sender, e) => File.WriteAllText(usersFilePath, users.ToJson());
User user = users[0];
LoginApiExtensions.LoginDataUpdated += (sender, e) => File.WriteAllText(usersFilePath, _users.ToJson());
User user = _users[0];
if (!await user.Login())
{
GlobalSettings.Logger.LogError($"账号{user.Account}登录失败!");
return;
}
if (!await StartLive(user))
//加载配置文件
LiveSetting liveSetting = LoadLiveSettingConfig();
if (liveSetting == null)
{
GlobalSettings.Logger.LogError($"加载直播设置配置文件失败!");
return;
}
//获取直播间信息
LiveRoomStreamDataInfo roomInfo = await LiveApi.GetRoomInfo(user);
if (roomInfo == null)
{
GlobalSettings.Logger.LogError($"开启直播失败!");
return;
}
//开始使用ffmpeg推流直播
await StartPublish(user, liveSetting, $"{roomInfo.Rtmp}{roomInfo.StreamLine}");

if (Console.IsInputRedirected || Console.IsOutputRedirected)
{
Expand All @@ -69,12 +87,10 @@ static async Task Main(string[] args)
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
private static async Task<bool> StartLive(User user)
private static async Task<StartLiveDataInfo> StartLive(User user, LiveSetting liveSetting)
{
try
{
//加载配置文件
LiveSetting liveSetting = LoadLiveSettingConfig();
//先停止历史直播
if (await LiveApi.StopLive(user))
{
Expand All @@ -92,18 +108,22 @@ private static async Task<bool> StartLive(User user)
GlobalSettings.Logger.LogInfo($"我的直播间地址:http://live.bilibili.com/{liveInfo.RoomId}");
GlobalSettings.Logger.LogInfo($"推流地址:{liveInfo.Rtmp.Addr}{liveInfo.Rtmp.Code}");
}
//开始使用ffmpeg推流直播
StartPublish(liveSetting, $"{liveInfo.Rtmp.Addr}{liveInfo.Rtmp.Code}");
return true;
return liveInfo;
}
catch (Exception ex)
{
GlobalSettings.Logger.LogError($"开启直播失败!错误:{ex.Message}");
return false;
return null;
}
}

private static bool StartPublish(LiveSetting setting, string url)
/// <summary>
/// 开始推流
/// </summary>
/// <param name="setting"></param>
/// <param name="url"></param>
/// <returns></returns>
private static async Task<bool> StartPublish(User user, LiveSetting setting, string url)
{
try
{
Expand Down Expand Up @@ -141,6 +161,22 @@ private static bool StartPublish(LiveSetting setting, string url)
while (isAutoRestart)
{
isAutoRestart = setting.AutoRestart;
while (!await NetworkTools.NetworkCheck())
{
GlobalSettings.Logger.LogInfo($"Wait for network...");
await Task.Delay(3000);
}
if (!await LiveRoomStateCheck(user))
{
GlobalSettings.Logger.LogInfo($"Start live failed...");
return false;
}
StartLiveDataInfo liveInfo = await StartLive(user, setting);
if (liveInfo == null)
{
GlobalSettings.Logger.LogInfo($"Start live failed...");
return false;
}
//启动
var proc = Process.Start(psi);
if (proc == null)
Expand Down Expand Up @@ -178,6 +214,11 @@ private static bool StartPublish(LiveSetting setting, string url)
GlobalSettings.Logger.LogInfo($"Cmd exited.");
}
}
if (isAutoRestart)
{
//如果开启了自动重试,那么等待60s后再次尝试
await Task.Delay(60000);
}
}
return true;
}
Expand All @@ -188,16 +229,33 @@ private static bool StartPublish(LiveSetting setting, string url)
}
}

private static string GetTitle()
{
string productName = GetAssemblyAttribute<AssemblyProductAttribute>().Product;
string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return $"{productName} v{version}";
}

private static T GetAssemblyAttribute<T>()
/// <summary>
/// 直播间状态检查
/// </summary>
/// <returns></returns>
private static async Task<bool> LiveRoomStateCheck(User user)
{
return (T)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(T), false)[0];
try
{
string info = await LoginApi.GetInfoAsync(user);
if (string.IsNullOrEmpty(info))
{
if (!await user.Login())
{
throw new Exception("User login failed. exit.");
}
}
LiveRoomStreamDataInfo roomInfo = await LiveApi.GetRoomInfo(user);
if (roomInfo == null)
{
return false;
}
return true;
}
catch
{
return false;
}
}

/// <summary>
Expand Down

0 comments on commit b410640

Please sign in to comment.