Xamarin形式:如何捕获Webview的视频/音频播放时间?

如何解决Xamarin形式:如何捕获Webview的视频/音频播放时间?

我正在使用Webview在我的项目中播放视频和音频,如以下屏幕截图所示。

enter image description here

从该页面返回时,我需要捕获视频/音频的播放时间。我对此进行了研究,但没有得到任何有用的信息。

有什么方法可以获取视频/音频的播放时间?

更新

视频: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

示例音频URL:http://catholic-brain.s3.amazonaws.com/qa/dc/cbrain-app/files/doc-lib/2017/08/16/11/21/59/604/head/Catholic-brain-01-The-Rosary-Song.mp3

我在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

示例音频URL:http://catholic-brain.s3.amazonaws.com/qa/dc/cbrain-app/files/doc-lib/2017/08/16/11/21/59/604/head/Catholic-brain-01-The-Rosary-Song.mp3

我的Vimeo视频没有扩展名,例如.mp4

Update2

因此,在播放视频之前,我们需要下载视频的配置。我看一下配置,有5种不同的配置。所以我们需要从渐进式列表中获取URL的值,对吧?

enter image description here

解决方法

很遗憾,我已经通过共享源链接在本地站点中进行了测试,但是无法获得播放时间。

视频URL:https://player.vimeo.com/video/434126696?api=1&player_id=player1

视频网址是包装好的播放器链接。我们需要播放器公开播放时间的javascript API。然后我们可以在本机代码中调用它。

音频URL:http://catholic-brain.s3.amazonaws.com/qa/dc/cbrain-app/files/doc-lib/2017/08/16/11/21/59/604/head/Catholic-brain-01-The-Rosary-Song.mp3

音频网址是原始来源(.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 audiovideo属性播放原始来源网址,我们可以调用js以使其在iOS中的currentTimeduration如下:

//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

要这样做,您需要做几件事:-

  1. 根据存储在 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
  1. 非常重要:-

MediaElement 位于预览版中,如果在应用程序启动时不执行以下操作,您几乎总是会收到 System.Reflection。抛出的TargetInvocationException 崩溃了,您会迷惑一阵子。

为避免这种情况,请暂时在App()构造函数中添加以下内容:-

Device.SetFlags(new[] { "MediaElement_Experimental" });
  1. 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; });
  1. 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.

enter image description here

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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-