Skip to content
This repository has been archived by the owner on Dec 20, 2023. It is now read-only.

替换直播API,支持HEVC/仅听音频等功能 #1003

Merged
merged 3 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/App/Controls/App/CommonImageEx/CommonImageEx.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ControlTemplate TargetType="local:CommonImageEx">
<controls:ImageEx
x:Name="Image"
CornerRadius="{TemplateBinding CornerRadius}"
EnableLazyLoading="True"
PlaceholderSource="/Assets/img_holder_rect.png"
PlaceholderStretch="Uniform"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ private void OnBackButtonClick(object sender, RoutedEventArgs e)

private async void OnLiveRefreshButtonClickAsync(object sender, RoutedEventArgs e)
{
if (ViewModel.CurrentPlayLine != null)
if (ViewModel.CurrentPlayUrl != null)
{
await ViewModel.ChangeLivePlayLineAsync(ViewModel.CurrentPlayLine.Order);
await ViewModel.ChangeAppLivePlayLineAsync(ViewModel.CurrentPlayUrl.Data);
}
}

Expand All @@ -269,18 +269,18 @@ private async void OnFormatListViewSelectionChangedAsync(object sender, Selectio

private async void OnLivePlayLineListViewSelectionChangedAsync(object sender, SelectionChangedEventArgs e)
{
if (_livePlayLineListView.SelectedItem is LivePlayLineViewModel data && ViewModel.CurrentPlayLine != data.Data)
if (_livePlayLineListView.SelectedItem is LiveAppPlayLineViewModel data2 && ViewModel.CurrentPlayUrl != data2)
{
await ViewModel.ChangeLivePlayLineAsync(data.Data.Order);
await ViewModel.ChangeAppLivePlayLineAsync(data2.Data);
}
}

private async void OnLiveQualityListViewSelectionChangedAsync(object sender, SelectionChangedEventArgs e)
{
if (_liveQualityListView.SelectedItem is LiveQualityViewModel data && ViewModel.CurrentLiveQuality != data.Data)
if (_liveQualityListView.SelectedItem is LiveAppQualityViewModel data2 && ViewModel.CurrentAppLiveQuality != data2.Data)
{
await ViewModel.ChangeLiveQualityAsync(data.Data.Quality);
_liveQualityButton.Flyout.Hide();
await ViewModel.ChangeLivePlayBehaviorAsync(data2.Data.Quality);
_liveQualityButton?.Flyout.Hide();
}
}

Expand Down Expand Up @@ -502,24 +502,24 @@ private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs
_formatListView.SelectedItem = ViewModel.FormatCollection.Where(p => p.Data.Quality == ViewModel.CurrentFormat.Quality).FirstOrDefault();
}
}
else if (e.PropertyName == nameof(ViewModel.CurrentLiveQuality))
else if (e.PropertyName == nameof(ViewModel.CurrentAppLiveQuality))
{
if (ViewModel.CurrentLiveQuality != null &&
if (ViewModel.CurrentAppLiveQuality != null &&
_liveQualityListView != null &&
(_liveQualityListView.SelectedItem == null ||
(_liveQualityListView.SelectedItem as LiveQualityViewModel).Data.Quality != ViewModel.CurrentLiveQuality.Quality))
(_liveQualityListView.SelectedItem as LiveAppQualityViewModel).Data.Quality != ViewModel.CurrentAppLiveQuality.Quality))
{
_liveQualityListView.SelectedItem = ViewModel.LiveQualityCollection.Where(p => p.Data.Quality == ViewModel.CurrentLiveQuality.Quality).FirstOrDefault();
_liveQualityListView.SelectedItem = ViewModel.LiveAppQualityCollection.Where(p => p.Data.Quality == ViewModel.CurrentAppLiveQuality.Quality).FirstOrDefault();
}
}
else if (e.PropertyName == nameof(ViewModel.CurrentPlayLine))
else if (e.PropertyName == nameof(ViewModel.CurrentPlayUrl))
{
if (ViewModel.CurrentPlayLine != null &&
if (ViewModel.CurrentPlayUrl != null &&
_liveQualityListView != null &&
(_livePlayLineListView.SelectedItem == null ||
(_livePlayLineListView.SelectedItem as LivePlayLineViewModel).Data.Order != ViewModel.CurrentPlayLine.Order))
(_livePlayLineListView.SelectedItem as LiveAppPlayLineViewModel).Data.Host != ViewModel.CurrentPlayUrl.Data.Host))
{
_livePlayLineListView.SelectedItem = ViewModel.LivePlayLineCollection.Where(p => p.Data.Order == ViewModel.CurrentPlayLine.Order).FirstOrDefault();
_livePlayLineListView.SelectedItem = ViewModel.LiveAppPlayLineCollection.Where(p => p.Data.Host == ViewModel.CurrentPlayUrl.Data.Host).FirstOrDefault();
}
}
else if (e.PropertyName == nameof(ViewModel.PlayerDisplayMode))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,24 @@
</Button>
</Grid>

<Grid
x:Name="CoverContainer"
Margin="-12"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.IsShowAudioCover, Converter={StaticResource BoolToVisibilityConverter}}">
<local:CommonImageEx ImageUrl="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.CoverUrl}" Stretch="UniformToFill" />
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{ThemeResource AppMaskAcrylicBrush}" />
<local:CommonImageEx
Width="120"
Height="120"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="60"
ImageUrl="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.CoverUrl}" />
</Grid>

<Rectangle
x:Name="InteractionControl"
HorizontalAlignment="Stretch"
Expand Down Expand Up @@ -731,7 +749,7 @@
x:Name="LiveQualityListView"
MinWidth="120"
Margin="4"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LiveQualityCollection}">
ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LiveAppQualityCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Data.Description}" />
Expand Down Expand Up @@ -760,13 +778,10 @@
x:Name="LivePlayLineListView"
MinWidth="120"
Margin="4"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LivePlayLineCollection}">
ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LiveAppPlayLineCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{loc:LocaleLocator Name=PlayLine}" />
<Run Text="{Binding Data.Order}" />
</TextBlock>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Expand Down
15 changes: 15 additions & 0 deletions src/App/Controls/Player/PlayerDashboard.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,22 @@
x:Name="LiveControlContainer"
Margin="0,0,0,4"
HorizontalAlignment="Stretch"
Spacing="8"
Visibility="{x:Bind ViewModel.IsLive, Mode=OneWay}">
<ToggleSwitch
x:Name="LiveAudioOnlySwitch"
Header="{loc:LocaleLocator Name=OnlyAudio}"
IsOn="{x:Bind ViewModel.IsLiveAudioOnly, Mode=OneWay}"
Toggled="OnLiveOnlyAudioToggledAsync">
<ToggleSwitch.HeaderTemplate>
<DataTemplate>
<TextBlock
Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{Binding}" />
</DataTemplate>
</ToggleSwitch.HeaderTemplate>
</ToggleSwitch>
<TextBlock
Style="{StaticResource BodyTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Expand Down
8 changes: 8 additions & 0 deletions src/App/Controls/Player/PlayerDashboard.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,13 @@ private void OnLikeButtonHoldingSuspend(object sender, EventArgs e)
{
_isLikeHoldSuspend = true;
}

private async void OnLiveOnlyAudioToggledAsync(object sender, RoutedEventArgs e)
{
if (ViewModel.IsLive && ViewModel.IsLiveAudioOnly != LiveAudioOnlySwitch.IsOn)
{
await ViewModel.ToggleLiveAudioAsync(LiveAudioOnlySwitch.IsOn);
}
}
}
}
10 changes: 10 additions & 0 deletions src/Controller/Controller.Uwp/BiliController.Live.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ public Task<LiveRoomDetail> GetLiveRoomDetailAsync(int roomId)
public Task<LivePlayInformation> GetLivePlayInformationAsync(int roomId, int quality = 4)
=> _liveProvider.GetLivePlayInformationAsync(roomId, quality);

/// <summary>
/// 获取直播间播放信息.
/// </summary>
/// <param name="roomId">直播间Id.</param>
/// <param name="quality">清晰度.</param>
/// <param name="audioOnly">是否仅播放音频.</param>
/// <returns>播放信息.</returns>
public Task<LiveAppPlayUrlInfo> GetAppLivePlayInformationAsync(int roomId, int quality = 150, bool audioOnly = false)
=> _liveProvider.GetAppLivePlayInformation(roomId, quality, audioOnly);

/// <summary>
/// 连接到直播间.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/Lib/Lib.Interfaces/ILiveProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ public interface ILiveProvider
/// <returns>播放信息.</returns>
Task<LivePlayInformation> GetLivePlayInformationAsync(int roomId, int quality);

/// <summary>
/// 获取直播间播放数据.
/// </summary>
/// <param name="roomId">直播间Id.</param>
/// <param name="quality">清晰度.</param>
/// <param name="audioOnly">是否仅音频.</param>
/// <returns>播放信息.</returns>
Task<LiveAppPlayUrlInfo> GetAppLivePlayInformation(int roomId, int quality, bool audioOnly);

/// <summary>
/// 进入直播间.
/// </summary>
Expand Down
28 changes: 28 additions & 0 deletions src/Lib/Lib.Uwp/LiveProvider/LiveProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ public async Task<LivePlayInformation> GetLivePlayInformationAsync(int roomId, i
return result.Data.Information;
}

/// <inheritdoc/>
public async Task<LiveAppPlayUrlInfo> GetAppLivePlayInformation(int roomId, int quality, bool audioOnly)
{
var queryParameter = new Dictionary<string, string>
{
{ Query.RoomId, roomId.ToString() },
{ Query.NoPlayUrl, "0" },
{ Query.Qn, quality.ToString() },
{ Query.Codec, Uri.EscapeDataString("0,1") },
{ Query.Device, "phone" },
{ Query.DeviceName, Uri.EscapeDataString("iPhone 13") },
{ Query.Dolby, "1" },
{ Query.Format, Uri.EscapeDataString("0,2") },
{ Query.Http, "1" },
{ Query.OnlyAudio, audioOnly ? "1" : "0" },
{ Query.OnlyVideo, "0" },
{ Query.Protocol, Uri.EscapeDataString("0,1") },
{ Query.NeedHdr, "0" },
{ Query.Mask, "0" },
{ Query.PlayType, "0" },
};

var request = await _httpProvider.GetRequestMessageAsync(HttpMethod.Get, Live.AppPlayInformation, queryParameter, RequestClientType.IOS);
var response = await _httpProvider.SendAsync(request);
var result = await _httpProvider.ParseAsync<ServerResponse<LiveAppPlayInformation>>(response);
return result.Data.PlayUrlInfo;
}

/// <inheritdoc/>
public async Task<LiveRoomDetail> GetLiveRoomDetailAsync(int roomId)
{
Expand Down
5 changes: 5 additions & 0 deletions src/Models/Models.App/Constants/ApiConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ public static class Live
/// 分区详情.
/// </summary>
public const string AreaDetail = _liveBase + "/xlive/app-interface/v2/second/getList";

/// <summary>
/// 移动应用上的播放信息.
/// </summary>
public const string AppPlayInformation = _liveBase + "/xlive/app-room/v2/index/getRoomPlayInfo";
}

public static class Article
Expand Down
10 changes: 9 additions & 1 deletion src/Models/Models.App/Constants/ServiceConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public static class Query
public const string LikeTime = "like_time";
public const string AtTime = "at_time";
public const string ReplyTime = "reply_time";
public const string Protocol = "protocal";
public const string Protocol = "protocol";
public const string Codec = "codec";
public const string PType = "ptype";
public const string Format = "format";
Expand All @@ -183,6 +183,14 @@ public static class Query
public const string CateId = "cate_id";
public const string ParentAreaId = "parent_area_id";
public const string SortType = "sort_type";
public const string NoPlayUrl = "no_playurl";
public const string Dolby = "dolby";
public const string Http = "http";
public const string OnlyAudio = "only_audio";
public const string OnlyVideo = "only_video";
public const string NeedHdr = "need_hdr";
public const string Mask = "mask";
public const string PlayType = "play_type";
}

public static class Sort
Expand Down
Loading