M3U8 plays with sound on one app but without sound on another - chromecast

I have a user with an m3u8 file that the content of the file looks like this:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=701214,CODECS="avc1.66.30, mp4a.40.34",RESOLUTION=640x360
chunklist.m3u8?wowzasessionid=1635263674
He claims this other app (not mine) is able to play that file with sound on the Chromecast whereas mine plays it without sound. I have not been able to reproduce his claims but since he insists this is true I figured I would check.
I'm using the reference player code pretty much unmodified except for this code which I got on this other post:
host.processManifest = function(manifest) {
if (manifest) {
return manifest.replace(/CODECS=\"avc1.66.([0-9]*)/g, 'CODECS=\"avc1.66.30');
}else{
return manifest;
}
};

Related

Xamarin Community Toolkit CameraView video file location supplied becomes invalid IOS and Android

I'm using the CameraView to capture a series of short videos. I want these videos to be viewable at a later time from within the app. I'm using the MediaCaptured event to get the path of captured videos and saving these paths in a SQLite db.
The first problem is on iOS, the path is valid while the app is open, but if I close the app and open it again the path is no longer valid. I've worked around this by copying the video to the AppDataDirectory but this seems bad because I haven't figured out how to delete the original so now two copies of the video exist.
The second problem is on both iOS and Android, after some amount of time (a few days or a week or more) these paths become invalid for some unknown reason.
What is the correct way to deal with this?
private void MediaCaptured(object obj)
{
MediaCapturedEventArgs args = obj as MediaCapturedEventArgs;
string sPath = "";
switch (Device.RuntimePlatform)
{
case Device.iOS:
//On iOS args.Video.File returns a path that isn't valid when the app is restarted. To get around this issue I am copying the file to the App Data Directory.
//The drawback is there are now two video files and I can't delete the original.
var pathSplit = args.Video.File.Split('/');
sPath = Path.Combine(FileSystem.AppDataDirectory, pathSplit[pathSplit.Length - 1]);
File.Copy(args.Video.File, sPath);
//TODO Should probalby be deleting the original video but not sure how (or if its possible).
break;
case Device.Android:
sPath = args.Video.File;
break;
}
SavePathToDB(sPath);
}

Xamarin Forms Video Player Sample - Get Video Bytes for Uploading

I'm implementing a video player in a Xamarin Forms app just like the video player sample provided by Xamarin
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/video-player/
I'm able to select a video from the phone gallery, set the video player source to the selected video, and play the video. How do I get the actual stream or bytes of the selected video so that I can upload it to Blob Storage?
I've tried
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) ..........
where fileName is the path and file name of the selected video as set to the video player source. It doesn't work as the Android file name string is not found. (When invoking this from xamarin forms). I realize the file name will be different even when on iOS. How do I reach down into the platform specific implementations and get the file bytes or stream of the selected file?
thanks
I would look into the libVLCSharp library which provides cross-platform .NET/Mono bindings for libVLC. They provide good support for Xamarin.Forms and the features you most likely need to implement the stream handling functionality. What you're trying to achieve won't be simple but it should be perfectly doable.
First, you should check out the documentation for Stream output:
Stream output is the name of the feature of VLC that allows to output any stream read by VLC to a file or as a network stream instead of displaying it.
Related tutorial: Stream to memory (smem) tutorial.
That should get you started but there will for sure be many caveats along the way. For example, if you try to play the video while capturing the bytes to be uploaded somewhere, you'll have to respect VERY tight timeframes. In case you take too long to process the stream, it will slow down the playback and the user experience suffers.
Edit: Another option you could look into is to interact directly with the MediaPlayer class of libVLC, as explained in this answer. The sample code is in C++ but the method names are very similar in the .NET bindings.
For example, the following piece of code:
libvlc_video_set_callbacks(mplayer,
lock_frame, unlock_frame,
0, user_data);
can be implemented with libVLCSharp by calling the SetVideoCallbacks(LibVLCVideoLockCb lockCb, LibVLCVideoUnlockCb unlockCb, LibVLCVideoDisplayCb displayCb) method in the binding library, as defined here.
You can do this pretty simply by using a DependencyService. You will need to adjust the below code to cater for a folder location that you're working with but, do this.
Change all of the "Test" namespaces to you're own project.
Add an interface into your shared project called IFileSystem that looks like this ...
using System;
namespace Test.Interfaces
{
public interface IFileSystem
{
byte[] GetFileInBytes(string fileName);
}
}
Create a dependency service down in each platform project. For this, I'm only supplying iOS and Android but as you'll see, the logic for both is essentially exactly the same, only the namespace differs ...
iOS
using System;
using System.IO;
using Test.Interfaces;
using Test.iOS.DependencyServices;
using Xamarin.Forms;
[assembly: Dependency(typeof(FileSystem))]
namespace Test.iOS.DependencyServices
{
public class FileSystem : IFileSystem
{
public byte[] GetFileInBytes(string fileName)
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);
fileName = Path.Combine(folder, fileName);
return File.Exists(fileName) ? File.ReadAllBytes(fileName) : null;
}
}
}
Android
using System;
using System.IO;
using Test.Interfaces;
using Test.Droid.DependencyServices;
using Xamarin.Forms;
[assembly: Dependency(typeof(FileSystem))]
namespace Test.Droid.DependencyServices
{
public class FileSystem : IFileSystem
{
public byte[] GetFileInBytes(string fileName)
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);
fileName = Path.Combine(folder, fileName);
return File.Exists(fileName) ? File.ReadAllBytes(fileName) : null;
}
}
}
... now call that from anywhere in your shared project.
var bytes = DependencyService.Get<IFileSystem>().GetFileInBytes("Test.mp4");
That should work for you, again though, you need to adjust the folder path to your appropriate location for each platform project. Essentially, this line is the one that may need to change ...
var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);
Alternatively, change that code to suit your requirements. If the file path you've been given contains the fully qualified location, then remove the logic to add the folder altogether.
Here's hoping that works for you.

WebRTC: Renegotiation in firefox

According to this article, re-negotiation is implemented in firefox v38 and we can add remove streams from same peerconnections without creating new ones, but I am unable to find any working demos to support that claim, and when I tried it, two users chating in video mode, I changing one of their stream to audio, I get the error:
NotSupportedError: removeStream not yet implemented
this tells the same, but this tells renegotiation events are supported, but isn't removeStream key part of renegotiation? I am using firefox version 39 in windows 7. I am confused, renegotiation is not yet supported in firefox, right?
Renegotiation is supported in Firefox.
Firefox just never implemented removeStream because the spec had changed to addTrack and removeTrack by the time renegotiation was implemented (some are suggesting that its removal was too hasty, so it may come back). addStream still works for backwards compatibility, because Firefox already supported it.
Note that removeTrack confusingly takes the RTCRtpSender returned from addTrack so the API is not a drop-in.
A polyfill would look something like this:
mozRTCPeerConnection.prototype.removeStream = function(stream) {
this.getSenders().forEach(sender =>
stream.getTracks().includes(sender.track) && this.removeTrack(sender));
}
The move to tracks was done to give users more flexibility, since tracks may belong to multiple streams, and not all tracks in a stream need be sent over a PeerConnection (or the same PeerConnection).
See this answer to a different question for a renegotiation example that works in Firefox.
Try using replaceTrack for individual tracks, instead of replacing the entire stream. This example assumes you have a peer connection pc1 and a new stream newStream to replace on it. Get the senders, and replace the tracks with appropriate tracks from the new stream. Working sample here.
Promise.all(pc1.getSenders().map(sender =>
sender.replaceTrack((sender.track.kind == "audio")?
newStream.getAudioTracks()[0] :
newStream.getVideoTracks()[0])))
.then(() => log("Flip!"))
.catch(failed);
Also note this, from your first link:
function screenShare() {
let screenConstraints = {video: {mediaSource: "screen"}};
navigator.mediaDevices.getUserMedia(screenConstraints)
.then(stream) {
stream.getTracks().forEach(track) {
screenStream = stream;
screenSenders.push(pc1.addTrack(track, stream));
});
});
}
Notice that this example calls pc1.addTrack not pc1.addStream
And in the same in reverse, for removing - pc1.removeTrack:
function stopScreenShare() {
screenStream.stop();
screenSenders.forEach(sender) {
pc1.removeTrack(sender);
});
}

File Activation in Windows Store app in C#?

I m tryin to make metro Media Player ,but I have a problem in file activation i.e when I open mp3 file from Windows explorer, it open my app But Doesn,t get Arguments, how can I get file or name of file in text block for which my app is launched,i saw many methods in different Websites,But I can't Solve,
here is a really good explanation on how to do this:
https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh779669.aspx
you can get the file name and file size here:
protected override void OnFileActivated(FileActivatedEventArgs args)
{
// TODO: Handle file activation
// The number of files received is args.Files.Size
// The first file is args.Files[0].Name
}

how to generate MSTEST results in Static folders

Is there a way to control the name of the MSTEST video recoding file names or the folder names with the test name. It seems to generate different guid everytime and thus very difficult to map the test with its corresponding video recording files.
The only solution I can see is to read the TRX file and map the guid to Test Name.
Any suggestions ??
If you're not opposed to doing it by hand, it's pretty easy. I encountered the same problem, and needed them to be somewhere predictable so I could email links to the videos. In the end my solution just ended up being to code in the functionality by hand. It's a bit involved, but not too difficult.
First, you'll need to have Expression Encoder 4 installed.
Then you'll need to add these references to your project:
Microsoft.Expression.Encoder
Microsoft.Expression.Encoder.Api2
Microsoft.Expression.Encoder.Types
Microsoft.Expression.Encoder.Utilities
Next, you need to add the following inclusion statements:
using Microsoft.Expression.Encoder.Profiles;
using Microsoft.Expression.Encoder.ScreenCapture;
Then you can use [TestInitialize] and [TestCleanup] to define the correct behavior. These methods will run at the beginning and end of each test respectively. This can be done something like this:
[TestInitialize]
public void startVideoCapture()
{
screenCapJob.CaptureRectangle = RectangleSelectionUtilities.GetScreenRect(0);
screenCapJob.CaptureMouseCursor = true;
screenCapJob.ShowFlashingBoundary = false;
screenCapJob.OutputScreenCaptureFileName = "path you want to save to";
screenCapJob.Start();
}
[TestCleanup]
public void stopVideoCapture()
{
screenCapJob.Stop();
}
Obviously this code needs some error and edge case handling, but it should get you started.
You should also know that the free version of Expression Encoder 4 limits you to 10 minutes per video file, so you may want to make a timer that will start a new video for you when it hits 10 minutes.

Resources