如何解决Xamarin形式:如何捕获Webview的视频/音频播放时间?
我正在使用Webview在我的项目中播放视频和音频,如以下屏幕截图所示。
从该页面返回时,我需要捕获视频/音频的播放时间。我对此进行了研究,但没有得到任何有用的信息。
有什么方法可以获取视频/音频的播放时间?
更新
视频:XAML
<local:VideoWebview
x:Name="web_view"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
</local:VideoWebview>
XAML.CS
if (Device.RuntimePlatform == Device.iOS)
{
Device.BeginInvokeOnMainThread(() =>
{
web_view.Url = videourl;
});
}
else
{
web_view.Source = videourl;
}
音频:XAML
<WebView
x:Name="web_view"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
</WebView>
XAML.CS
web_view.Source = audiourl;
示例视频网址:https://player.vimeo.com/video/434126696?api=1&player_id=player1
我在ios视频webview中使用自定义渲染器作为透明背景。
public class VideoWebviewRenderer : ViewRenderer<VideoWebview,WKWebView>
{
WKWebView wkWebView;
protected override void OnElementChanged(ElementChangedEventArgs<VideoWebview> e)
{
base.OnElementChanged(e);
if (Control == null)
{
WKWebViewConfiguration configuration = new WKWebViewConfiguration();
configuration.AllowsInlineMediaPlayback = true;
wkWebView = new WKWebView(CGRect.Empty,configuration);
//transparent background
wkWebView = new WKWebView(CGRect.Empty,configuration);
wkWebView.BackgroundColor = UIColor.Clear;
wkWebView.ScrollView.BackgroundColor = UIColor.Clear;
wkWebView.Opaque = false;
if (Element.Url != null)
{
wkWebView.LoadRequest(new NSUrlRequest(new NSUrl((Element).Url)));
}
SetNativeControl(wkWebView);
}
}
protected override void OnElementPropertyChanged(object sender,PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(nameof(Element.Url)))
{
wkWebView.LoadRequest(new NSUrlRequest(new NSUrl((Element).Url)));
}
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
Control.Frame = rect;
}
}
更新1
@Pete我尝试过MediaElement
,但视频或音频未显示在UI上。
我已经完成了一个示例并将其上传到here,能否请您检查我所缺少的内容?
我没有迈出第一步,如何为Vimeo视频创建视频流?对于音频文件,我需要创建流吗?您能解释一下音频部分的实现吗?我已经在示例中添加了音频部分,它在UI上不可见,但是我可以听到音频。
示例视频网址:https://player.vimeo.com/video/434126696?api=1&player_id=player1
我的Vimeo视频没有扩展名,例如.mp4
Update2
因此,在播放视频之前,我们需要下载视频的配置。我看一下配置,有5种不同的配置。所以我们需要从渐进式列表中获取URL的值,对吧?
解决方法
很遗憾,我已经通过共享源链接在本地站点中进行了测试,但是无法获得播放时间。
视频URL:https://player.vimeo.com/video/434126696?api=1&player_id=player1
视频网址是包装好的播放器链接。我们需要播放器公开播放时间的javascript API。然后我们可以在本机代码中调用它。
音频网址是原始来源(.mp3),我们只能获取其持续时间。
NSString url = new NSString("xxx.mp3");
if (url.PathExtension == new NSString("mp3"))
{
NSUrl videoUrl = new NSUrl(url.ToString());
AVUrlAsset avUrl = new AVUrlAsset(videoUrl,new NSDictionary(AVUrlAsset.PreferPreciseDurationAndTimingKey,true));
CMTime time = avUrl.Duration;
float seconds = time.Value / time.TimeScale;
Console.WriteLine("====================" + seconds );
}
如果需要获取播放时间,还可以使用包装的音频播放器。并公开其播放时间的javascript API。
通常,如果使用 HTML 的audio
和video
属性播放原始来源网址,我们可以调用js以使其在iOS中的currentTime
和duration
如下:
//video
string JsStr = "(document.getElementsByTagName(\"video\")[0]).currentTime";
// audio
//string JsStr = "(document.getElementsByTagName(\"audio\")[0]).currentTime";
WKJavascriptEvaluationResult handler = (NSObject result,NSError err) =>
{
if (err != null)
{
System.Console.WriteLine("================"+err);
}
if (result != null)
{
System.Console.WriteLine("currentTime is : "+result);
}
};
wkWebView.EvaluateJavaScript(JsStr,handler);
,
下面是如何使用 Xamarin.Forms 进行此操作的答案,正如您在评论中提到的那样,如果有任何其他播放器可以获取播放时间,那么这里是:-
要在 Xamarin.Forms 中执行此操作,可以使用 Xamarin.Forms 4.5 中引入的 MediaElement 。
要这样做,您需要做几件事:-
- 根据存储在 Vimeo 上的视频配置确定要播放的流。
您可以通过检查从以下网址返回的 JSON 来获得此配置:-
http://player.vimeo.com/video/36671239/config
即,其中 36671239 是您在 Vimeo 上的视频ID 。
以下是其中一种流的示例,它是 mp4 视频格式:-
https://vod-progressive.akamaized.net/exp=1597882056~acl=%2A%2F84157673.mp4%2A~hmac=1230da01c045577d047b307a0d3679b46cc9b0bbc1d0312e272b67bb31d5129c/vimeo-prod-skyfire-std-us/01/2334/1/36671239/84157673.mp4
- 非常重要:-
MediaElement 位于预览版中,如果在应用程序启动时不执行以下操作,您几乎总是会收到 System.Reflection。抛出的TargetInvocationException 崩溃了,您会迷惑一阵子。
为避免这种情况,请暂时在App()构造函数中添加以下内容:-
Device.SetFlags(new[] { "MediaElement_Experimental" });
- MediaElement 目前不为 Position 属性发出 PropertyChanged 通知。
但是,要解决此问题,您可以使用自己的 Timer (计时器),并检索公开视频的 Position (位置)属性,然后使用该属性。
这绝对不适合生产,因为您不希望计时器始终运行,而只是说明您可以实现所需的功能:-
在构造函数中设置一个活动计时器,如下所示:-
Device.StartTimer(TimeSpan.FromSeconds(0.5),() =>
{
if (videoPlayer.CurrentState == MediaElementState.Playing)
{
string strPlayPosition = videoPlayer.Position.ToString(@"hh\:mm\:ss");
lblCurrentVideoTime.Text = strPlayPosition;
}
return true;
});
- 在 ContentPage 上添加以下内容:-
<Grid BackgroundColor="#242475">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement
x:Name="videoPlayer"
Grid.Row="0"
Aspect="AspectFit"
BackgroundColor="Black"
ShowsPlaybackControls="True"
Source="https://vod-progressive.akamaized.net/exp=1597882056~acl=%2A%2F84157673.mp4%2A~hmac=1230da01c045577d047b307a0d3679b46cc9b0bbc1d0312e272b67bb31d5129c/vimeo-prod-skyfire-std-us/01/2334/1/36671239/84157673.mp4" />
<StackLayout
Grid.Row="1"
HorizontalOptions="CenterAndExpand"
Orientation="Horizontal"
VerticalOptions="Center">
<Label
FontAttributes="Bold"
FontSize="18"
Text="CURRENT VIDEO TIME : "
TextColor="White" />
<Label
x:Name="lblCurrentVideoTime"
FontAttributes="Bold"
FontSize="18"
TextColor="White" />
</StackLayout>
</Grid>
and you will see something like the following,with whatever video you would like to watch from Vimeo:-
The MediaElement can also be used on audio as well.
Update 1
I've taken a look at your video id you mentioned (434126696).
and there are multiple mp4 streams that are specified in the configuration.
One such stream is:-
https://vod-progressive.akamaized.net/exp=1598157872~acl=%2Fvimeo-prod-skyfire-std-us%2F01%2F1825%2F17%2F434126696%2F1890592390.mp4~hmac=a0ac67f23fdd68df9d16fb2db33e8b2b00d0dc3626375d2a4c6ba7a5203b935e/vimeo-prod-skyfire-std-us/01/1825/17/434126696/1890592390.mp4
if you place this mp4 link in the MediaElement,in my example,like so:-
<MediaElement
x:Name="videoPlayer"
Grid.Row="0"
Aspect="AspectFit"
BackgroundColor="Black"
ShowsPlaybackControls="True"
Source="https://vod-progressive.akamaized.net/exp=1598157872~acl=%2Fvimeo-prod-skyfire-std-us%2F01%2F1825%2F17%2F434126696%2F1890592390.mp4~hmac=a0ac67f23fdd68df9d16fb2db33e8b2b00d0dc3626375d2a4c6ba7a5203b935e/vimeo-prod-skyfire-std-us/01/1825/17/434126696/1890592390.mp4" />
You will see your video playing.
You have to analyze the JSON returned. In C# you can download the configuration like so:-
<Grid BackgroundColor="#242475">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement
x:Name="videoPlayer"
Grid.Row="0"
Aspect="AspectFit"
BackgroundColor="Black"
ShowsPlaybackControls="True"
Source="https://vod-progressive.akamaized.net/exp=1597882056~acl=%2A%2F84157673.mp4%2A~hmac=1230da01c045577d047b307a0d3679b46cc9b0bbc1d0312e272b67bb31d5129c/vimeo-prod-skyfire-std-us/01/2334/1/36671239/84157673.mp4" />
<StackLayout
Grid.Row="1"
HorizontalOptions="CenterAndExpand"
Orientation="Horizontal"
VerticalOptions="Center">
<Label
FontAttributes="Bold"
FontSize="18"
Text="CURRENT VIDEO TIME : "
TextColor="White" />
<Label
x:Name="lblCurrentVideoTime"
FontAttributes="Bold"
FontSize="18"
TextColor="White" />
</StackLayout>
</Grid>
然后,如果您使用 JSON 检查器,您将能够看到以不同分辨率为视频公开的各种 mp4 流。然后,您可以选择一个想要用来显示视频的视频。
,用于执行JSON提取的代码:
public void ExtractConfiguration(string vimeoUrl)
{
try
{
using (var objClient = new WebClient())
{
string strResponse = objClient.DownloadString(vimeoUrl);
VimeoConfig vimeoConfig = new VimeoConfig();
vimeoConfig = JsonConvert.DeserializeObject<VimeoConfig>(strResponse.ToString());
string url = vimeoConfig.request.files.progressive[0].url;
videoPlayer.Source = url;
}
}
catch(Exception e)
{
Debug.WriteLine("Exception:>>"+e);
}
}
//Model
public class VimeoConfig
{
public Request request { get; set; }
}
public class Request
{
public Files files { get; set; }
}
public class Files
{
public List<Progressive> progressive { get; set; }
}
public class Progressive
{
public string url { get; set; }
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。