Ich habe ein funktionierendes DNLA-Gerät (Xbox360, PSP ...) RSS Video-Feed-Reader in C#. Es analysiert .OPML-Dateien, um den Feed-URI zu erhalten.RSS Video Feed Enhancement - müssen Dauer auf Elemente, die es nicht in Feed enthalten
Manchmal hat ein RSS-Feed-Element keinen Wert für die Dauer, daher programmiere ich einen Standarddauerwert hart, wenn dies nicht der Fall ist.
Ich möchte die tatsächliche Dauer der Videodatei erhalten.
Meine Idee ist es, httpWebRequest zu verwenden, um einen Byte-Stream zu erhalten und die Informationen in den Dateien binäre MetaData, falls verfügbar, zu suchen. Ich denke, es könnte getan werden, kann aber keine ähnlichen Beispiele finden.
Der Prozess muss schnell sein und muss nicht die gesamte Videodatei abrufen, da der Wert für die Dauer nur zum Erstellen des Menüs benötigt wird. Die Dateien, die ich auf diese Weise verarbeiten soll, sind .flv, .m4v und .mp4. Das folgende Beispiel zeigt eine .flv-Datei:
using System;
using System.IO;
using System.Text;
using System.Net;
namespace myRSSVideoReader
{
public static class FlvMetadataReader
{
private const int BufferLength = 1000;
/// <summary>
/// Reads the meta information (if present) in an FLV
/// </summary>
/// <param name="uri">The path to the FLV file</returns>
public static MediaMetadataInfo GetMetadataInfo(string uri)
{
bool hasMetaData = false;
double duration = 0;
double width = 0;
double height = 0;
double videoDataRate = 0;
double audioDataRate = 0;
double frameRate = 0;
DateTime creationDate = DateTime.MinValue;
WebRequest req = HttpWebRequest.Create(uri);
WebResponse res = req.GetResponse();
Stream s = res.GetResponseStream(); //Source
MemoryStream ms = new MemoryStream((int)(res as HttpWebResponse).ContentLength); //Destination
byte[] b = new byte[BufferLength]; //Buffer
int cnt = 0;
do
{
//Read up to 1000 bytes from the response stream
cnt = s.Read(b, 0, BufferLength);
//Write the number of bytes actually read
ms.Write(b, 0, cnt);
}
while (cnt > 0);
try
{
// read where "onMetaData"
byte[] bytes = new byte[10];
ms.Seek(27, SeekOrigin.Begin);
int result = ms.Read(bytes, 0, 10);
// if "onMetaData" exists then proceed to read the attributes
string onMetaData = ByteArrayToString(bytes);
if (onMetaData == "onMetaData")
{
hasMetaData = true;
// 16 bytes past "onMetaData" is the data for "duration"
duration = GetNextDouble(ms, 16, 8);
// 8 bytes past "duration" is the data for "width"
width = GetNextDouble(ms, 8, 8);
// 9 bytes past "width" is the data for "height"
height = GetNextDouble(ms, 9, 8);
// 16 bytes past "height" is the data for "videoDataRate"
videoDataRate = GetNextDouble(ms, 16, 8);
// 16 bytes past "videoDataRate" is the data for "audioDataRate"
audioDataRate = GetNextDouble(ms, 16, 8);
// 12 bytes past "audioDataRate" is the data for "frameRate"
frameRate = GetNextDouble(ms, 12, 8);
// read in bytes for creationDate manually
ms.Seek(17, SeekOrigin.Current);
byte[] seekBytes = new byte[24];
result = ms.Read(seekBytes, 0, 24);
string dateString = ByteArrayToString(seekBytes);
// create .NET readable date string
// cut off Day of Week
dateString = dateString.Substring(4);
// grab 1) month and day, 2) year, 3) time
dateString = dateString.Substring(0, 6) + " " + dateString.Substring(16, 4) + " " + dateString.Substring(7, 8);
// .NET 2.0 has DateTime.TryParse
try
{
creationDate = Convert.ToDateTime(dateString);
}
catch(Exception)
{
// no error handling
}
}
}
catch (Exception)
{
// no error handling
}
finally
{
ms.Close();
ms.Dispose();
}
Uri newUri = new Uri(uri);
string filename = Path.GetFileName(newUri.AbsoluteUri);
return new MediaMetadataInfo(hasMetaData, filename, duration, width, height, videoDataRate, audioDataRate, frameRate, creationDate);
}
private static Double GetNextDouble(MemoryStream ms, int offset, int length)
{
// move the desired number of places in the array
ms.Seek(offset, SeekOrigin.Current);
// create byte array
byte[] bytes = new byte[length];
// read bytes
int result = ms.Read(bytes, 0, length);
// convert to double (all flass values are written in reverse order)
return ByteArrayToDouble(bytes, true);
}
private static String ByteArrayToString(byte[] bytes)
{
string byteString = string.Empty;
foreach (byte b in bytes)
{
byteString += Convert.ToChar(b).ToString();
}
return byteString;
}
private static Double ByteArrayToDouble(byte[] bytes, bool readInReverse)
{
if (bytes.Length != 8)
throw new Exception("bytes must be exactly 8 in Length");
if (readInReverse)
Array.Reverse(bytes);
return BitConverter.ToDouble(bytes, 0);
}
}
}
Kann dies getan werden? Ich bin ein .flv uri von abc News RSS-Feed, um als ein Beispiel zu verwenden: http://video-cdn.abcnew.go.com/090713_ann
_skinnydip.flv Jede Hilfe wäre willkommen.
Ja, ich finde das heraus. Viele Mediendateien haben keine Metadaten. Also bin ich an der gleichen Stelle, die ich war, bevor ich es überprüft habe, aber für die Dateien, die ... –
Der Trick für mp4, um Dauer zu erhalten, benötigen Sie den letzten Zeitstempel (der erste ist 0:00:00) aus den Bytes. Es gibt einige Byteverschiebungen, aber es funktioniert und ist schnell. Das ist nur für die Dauer. Sagen Sie, wenn Sie wollen, Höhe, Breite, das ist in der Kopfzeile. Auch die httpWebRequest mit einem Minus AddRange (-1024), Sie erhalten Daten aus der Länge der Datei rückwärts 1024 als Ausgangspunkt: bis zum Ende der Datei. Cool. –