从mplayer读取控制台输出到解析轨道的位置/长度

时间:2016-03-27 22:30:20

标签: linux vb.net mono console mplayer

当你运行mplayer时,它会显示播放曲目的位置和长度(在其他一些信息中),我所假设的是stdout。

这是mplayer的输出示例:

MPlayer2 2.0-728-g2c378c7-4+b1 (C) 2000-2012 MPlayer Team
Cannot open file '/home/pi/.mplayer/input.conf': No such file or directory
Failed to open /home/pi/.mplayer/input.conf.
Cannot open file '/etc/mplayer/input.conf': No such file or directory
Failed to open /etc/mplayer/input.conf.

Playing Bomba Estéreo - La Boquilla [Dixone Remix].mp3.
Detected file format: MP2/3 (MPEG audio layer 2/3) (libavformat)
[mp3 @ 0x75bc15b8]max_analyze_duration 5000000 reached
[mp3 @ 0x75bc15b8]Estimating duration from bitrate, this may be inaccurate
[lavf] stream 0: audio (mp3), -aid 0
Clip info:
 album_artist: Bomba Estéreo
 genre: Latin
 title: La Boquilla [Dixone Remix]
 artist: Bomba Estéreo
 TBPM: 109
 TKEY: 11A
 album: Unknown
 date: 2011
Load subtitles in .
Selected audio codec: MPEG 1.0/2.0/2.5 layers I, II, III [mpg123]
AUDIO: 44100 Hz, 2 ch, s16le, 320.0 kbit/22.68% (ratio: 40000->176400)
AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
Video: no video
Starting playback...
A:  47.5 (47.4) of 229.3 (03:49.3)  4.1%

最后一行(A: 47.5 (47.4) of 229.3 (03:49.3) 4.1%)是我尝试阅读的内容,但由于某种原因,Process.OutputDataReceived事件处理程序从未收到它。

我错过了什么吗? mplayer是否采用了一些非标准的方式输出" A:"线到控制台?

以下是代码以防万一:

Public Overrides Sub Play()
    player = New Process()
    player.EnableRaisingEvents = True

    With player.StartInfo
        .FileName = "mplayer"
        .Arguments = String.Format("-ss {1} -endpos {2} -volume {3} -nolirc -vc null -vo null ""{0}""",
                                   tmpFileName,
                                   mTrack.StartTime,
                                   mTrack.EndTime,
                                   100)

        .CreateNoWindow = False
        .UseShellExecute = False
        .RedirectStandardOutput = True
        .RedirectStandardError = True
        .RedirectStandardInput = True
    End With

    AddHandler player.OutputDataReceived, AddressOf DataReceived
    AddHandler player.ErrorDataReceived, AddressOf DataReceived
    AddHandler player.Exited, Sub() KillPlayer()

    player.Start()
    player.BeginOutputReadLine()
    player.BeginErrorReadLine()

    waitForPlayer.WaitOne()

    KillPlayer()
End Sub

Private Sub DataReceived(sender As Object, e As DataReceivedEventArgs)
    If e.Data = Nothing Then Exit Sub

    If e.Data.Contains("A: ") Then
        ' Parse the data
    End If
End Sub

2 个答案:

答案 0 :(得分:2)

显然,唯一的解决方案是在“奴隶”模式下运行mplayer,如下所述:http://www.mplayerhq.hu/DOCS/tech/slave.txt

在这种模式下,我们可以向mplayer发送命令(通过stdin),响应(如果有的话)将通过stdout发送。

这是一个非常简单的实现,显示mplayer的当前位置(以秒为单位):

using System;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;

namespace TestMplayer {
    class MainClass {
        private static Process player;

        public static void Main(string[] args) {
            String fileName = "/home/pi/Documents/Projects/Raspberry/RPiPlayer/RPiPlayer/bin/Electronica/Skrillex - Make It Bun Dem (Damian Marley) [Butch Clancy Remix].mp3";
            player = new Process();
            player.EnableRaisingEvents = true;

            player.StartInfo.FileName = "mplayer";
            player.StartInfo.Arguments = String.Format("-slave -nolirc -vc null -vo null \"{0}\"", fileName);

            player.StartInfo.CreateNoWindow = false;
            player.StartInfo.UseShellExecute = false;
            player.StartInfo.RedirectStandardOutput = true;
            player.StartInfo.RedirectStandardError = true;
            player.StartInfo.RedirectStandardInput = true;

            player.OutputDataReceived += DataReceived;

            player.Start();
            player.BeginOutputReadLine();
            player.BeginErrorReadLine();

            Thread getPosThread = new Thread(GetPosLoop);
            getPosThread.Start();
        }

        private static void DataReceived(object o, DataReceivedEventArgs e) {
            Console.Clear();
            Console.WriteLine(e.Data);
        }

        private static void GetPosLoop() {
            do {
                Thread.Sleep(250);
                player.StandardInput.Write("get_time_pos" + Environment.NewLine);
            } while(!player.HasExited);
        }
    }
}

答案 1 :(得分:1)

我发现另一个以类似方式工作的应用程序存在同样的问题( dbPowerAmp ),在我的情况下,问题是流程输出使用 Unicode 编码以编写stdout缓冲区,因此我必须将 StandardOutputEncoding StandardError 设置为 Unicode 才能开始读取。

您的问题似乎是一样的,因为如果在您发布的输出中找不到“A”,清楚地显示现有的“A”,那么可能意味着当您使用当前编码读取时,该字符会有所不同用来读取输出。

因此,尝试在阅读流程输出时设置正确的编码,尝试将它们设置为 Unicode