how to play multiple videos one after the another in xamarin cross platform form c#
I have tried using list, array but the problem is that the last video only gets played, rest videos just doesnt play.
MediaQueue mq = new MediaQueue();
MediaFile mf = new MediaFile();
if (PlayStopButtonText.Text == "Play")
{
/*string videoUrl1 = "https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4";
string videoUrl = "https://sec.ch9.ms/ch9/e68c/690eebb1-797a-40ef-a841-c63dded4e68c/Cognitive-Services-Emotion_high.mp4";
CrossMediaManager.Current.Play(videoUrl,MediaFileType.Video,ResourceAvailability.Remote);
//CrossMediaManager.Current.PlayNext();*/
mf.Url = videoUrll;
mf.Type = MediaFileType.Video;
mq.Insert(0,mf);
mf.Url = videoUrl;
mf.Type = MediaFileType.Video;
mq.Insert(1, mf);
foreach(var item in mq)
{
CrossMediaManager.Current.Play(item.Url,MediaFileType.Video);
}
}
I am building an android application where a user can view some listed video. Those videos are categories into some channel. Once a channel is selected by user I want to cache all the video related to that channel in my cache memory so can play the video when there is no internet also.
Can anyone have more understanding about video cache without playing please help me in understanding how I can achieve this task.
Right now I am able to cache video If it's played using some library.
I have find the following working solution for caching video in background (single/multiple) using below lib, no need of player/video_view.use AsyncTaskRunner
Videocaching Lib
Add following in line in your gradle file
compile 'com.danikula:videocache:2.7.0'
Since we just need to kick start the prefetching, no need to do anything in while loop.
Or we can use ByteArrayOutputStream to write down the data to disk.
URL url = null;
try {
url = new URL(cachingUrl(cachingUrl));
InputStream inputStream = url.openStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
//nothing to do
}
} catch (IOException e) {
e.printStackTrace();
}
Important code from lib. to do
Create static instance in application class using following code
private HttpProxyCacheServer proxy;
public static HttpProxyCacheServer getProxy(Context context) {
Applications app = (Applications) context.getApplicationContext();
return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
}
private HttpProxyCacheServer newProxy() {
//return new HttpProxyCacheServer(this);
return new HttpProxyCacheServer.Builder(this)
.cacheDirectory(CacheUtils.getVideoCacheDir(this))
.maxCacheFilesCount(40)
.maxCacheSize(1024 * 1024 * 1024)
.build();
}
Write following code in your activity to pass url
public String cachingUrl(String urlPath) {
return Applications.getProxy(this).getProxyUrl(urlPath, true);
}
In my app : I wayt to pick a video from gallery and upload it to
youtube as unlisted with title, description.I got token.But idk how to
send post request.Any advice or sample code please ?
Please check this code:
// Sample java code for videos.insert
public static void main(String[] args) throws IOException {
try {
YouTube youtube = getYouTubeService();
String mime_type = "video/*";
String media_filename = "sample_video.flv";
HashMap<String, String> parameters = new HashMap<>();
parameters.put("part", "snippet,status");
Video video = new Video();
VideoSnippet snippet = new VideoSnippet();
snippet.set("categoryId", "22");
snippet.set("description", "Description of uploaded video.");
snippet.set("title", "Test video upload");
VideoStatus status = new VideoStatus();
status.set("privacyStatus", "private");
video.setSnippet(snippet);
video.setStatus(status);
InputStreamContent mediaContent = new InputStreamContent(mime_type,
ApiExample.class.getResourceAsStream(media_filename));
YouTube.Videos.Insert videosInsertRequest = youtube.videos().insert(parameters.get("part").toString(), video, mediaContent);
MediaHttpUploader uploader = videosInsertRequest.getMediaHttpUploader();
Video response = videosInsertRequest.execute();
System.out.println(response);
}
}
More info: YouTube Developer Documentation
I'm building an android app using Xamarin. The requirement of the app is to capture video from the camera and encode the video to send it across to a server.
Initially, I was using an encoder library on the server-side to encode recorded video but it was proving to be extremely unreliable and inefficient especially for large-sized video files. I have posted my issues on another thread here
I then decided to encode the video on the client-side and then send it to the server. I've found encoding to be a bit complicated and there isn't much information available on how this can be done. So, I searched for the only way I knew how to encode a video that is by using FFmpeg codec. I've found some solutions. There's a project on GitHub that demonstrates how FFmpeg is used inside a Xamarin android project. However, running the solution doesn't give any output. The project has a binary FFmpeg file which is installed to the phone directory using the code below:
_ffmpegBin = InstallBinary(XamarinAndroidFFmpeg.Resource.Raw.ffmpeg, "ffmpeg", false);
Below is the example code for encoding video into a different set of outputs:
_workingDirectory = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var sourceMp4 = "cat1.mp4";
var destinationPathAndFilename = System.IO.Path.Combine (_workingDirectory, "cat1_out.mp4");
var destinationPathAndFilename2 = System.IO.Path.Combine (_workingDirectory, "cat1_out2.mp4");
var destinationPathAndFilename4 = System.IO.Path.Combine (_workingDirectory, "cat1_out4.wav");
if (File.Exists (destinationPathAndFilename))
File.Delete (destinationPathAndFilename);
CreateSampleFile(Resource.Raw.cat1, _workingDirectory, sourceMp4);
var ffmpeg = new FFMpeg (this, _workingDirectory);
var sourceClip = new Clip (System.IO.Path.Combine(_workingDirectory, sourceMp4));
var result = ffmpeg.GetInfo (sourceClip);
var br = System.Environment.NewLine;
// There are callbacks based on Standard Output and Standard Error when ffmpeg binary is running as a process:
var onComplete = new MyCommand ((_) => {
RunOnUiThread(() =>_logView.Append("DONE!" + br + br));
});
var onMessage = new MyCommand ((message) => {
RunOnUiThread(() =>_logView.Append(message + br + br));
});
var callbacks = new FFMpegCallbacks (onComplete, onMessage);
// 1. The idea of this first test is to show that video editing is possible via FFmpeg:
// It results in a 150x150 movie that eventually zooms on a cat ear. This is desaturated, and there's a fade-in.
var filters = new List<VideoFilter> ();
filters.Add (new FadeVideoFilter ("in", 0, 100));
filters.Add(new CropVideoFilter("150","150","0","0"));
filters.Add(new ColorVideoFilter(1.0m, 1.0m, 0.0m, 0.5m, 1.0m, 1.0m, 1.0m, 1.0m));
var outputClip = new Clip (destinationPathAndFilename) { videoFilter = VideoFilter.Build (filters) };
outputClip.H264_CRF = "18"; // It's the quality coefficient for H264 - Default is 28. I think 18 is pretty good.
ffmpeg.ProcessVideo(sourceClip, outputClip, true, new FFMpegCallbacks(onComplete, onMessage));
//2. This is a similar version in command line only:
string[] cmds = new string[] {
"-y",
"-i",
sourceClip.path,
"-strict",
"-2",
"-vf",
"mp=eq2=1:1.68:0.3:1.25:1:0.96:1",
destinationPathAndFilename2,
"-acodec",
"copy",
};
ffmpeg.Execute (cmds, callbacks);
// 3. This lists codecs:
string[] cmds3 = new string[] {
"-codecs",
};
ffmpeg.Execute (cmds, callbacks);
// 4. This convers to WAV
// Note that the cat movie just has some silent house noise.
ffmpeg.ConvertToWaveAudio(sourceClip, destinationPathAndFilename4, 44100, 2, callbacks, true);
I have tried different commands but no output file is generated. I have tried to use another project found here but this one has the same issue. I don't get any errors but no output file is generated. I'm really hoping someone can help me find a way I can manage to use FFmpeg in my project or some way to compress video to transport it to the server.
I will really appreciate if someone can point me in the right direction.
Just figure how to get the output by adding the permission in AndroidManifest file.
android.permission.WRITE_EXTERNAL_STORAG
Please read the update on the repository, it says that there is a second package, Xamarin.Android.MP4Transcoder for Android 6.0 onwards.
Install NuGet https://www.nuget.org/packages/Xamarin.Android.MP4Transcoder/
await Xamarin.MP4Transcoder.Transcoder
.For720pFormat()
.ConvertAsync(inputFile, ouputFile, f => {
onProgress?.Invoke((int)(f * (double)100), 100);
});
return ouputFile;
For Previous Android versions
Soruce Code https://github.com/neurospeech/xamarin-android-ffmpeg
Install-Package Xamarin.Android.FFmpeg
Use this as template, this lets you log output as well as calculates progress.
You can take a look at source, this one downloads ffmpeg and verifies sha1 hash on first use.
public class VideoConverter
{
public VideoConverter()
{
}
public File ConvertFile(Context contex,
File inputFile,
Action<string> logger = null,
Action<int,int> onProgress = null)
{
File ouputFile = new File(inputFile.CanonicalPath + ".mpg");
ouputFile.DeleteOnExit();
List<string> cmd = new List<string>();
cmd.Add("-y");
cmd.Add("-i");
cmd.Add(inputFile.CanonicalPath);
MediaMetadataRetriever m = new MediaMetadataRetriever();
m.SetDataSource(inputFile.CanonicalPath);
string rotate = m.ExtractMetadata(Android.Media.MetadataKey.VideoRotation);
int r = 0;
if (!string.IsNullOrWhiteSpace(rotate)) {
r = int.Parse(rotate);
}
cmd.Add("-b:v");
cmd.Add("1M");
cmd.Add("-b:a");
cmd.Add("128k");
switch (r)
{
case 270:
cmd.Add("-vf scale=-1:480,transpose=cclock");
break;
case 180:
cmd.Add("-vf scale=-1:480,transpose=cclock,transpose=cclock");
break;
case 90:
cmd.Add("-vf scale=480:-1,transpose=clock");
break;
case 0:
cmd.Add("-vf scale=-1:480");
break;
default:
break;
}
cmd.Add("-f");
cmd.Add("mpeg");
cmd.Add(ouputFile.CanonicalPath);
string cmdParams = string.Join(" ", cmd);
int total = 0;
int current = 0;
await FFMpeg.Xamarin.FFMpegLibrary.Run(
context,
cmdParams
, (s) => {
logger?.Invoke(s);
int n = Extract(s, "Duration:", ",");
if (n != -1) {
total = n;
}
n = Extract(s, "time=", " bitrate=");
if (n != -1) {
current = n;
onProgress?.Invoke(current, total);
}
});
return ouputFile;
}
int Extract(String text, String start, String end)
{
int i = text.IndexOf(start);
if (i != -1)
{
text = text.Substring(i + start.Length);
i = text.IndexOf(end);
if (i != -1)
{
text = text.Substring(0, i);
return parseTime(text);
}
}
return -1;
}
public static int parseTime(String time)
{
time = time.Trim();
String[] tokens = time.Split(':');
int hours = int.Parse(tokens[0]);
int minutes = int.Parse(tokens[1]);
float seconds = float.Parse(tokens[2]);
int s = (int)seconds * 100;
return hours * 360000 + minutes * 60100 + s;
}
}
I'm trying to build my own music player for Android.
For a listing I need the metadata of the songs, so I'm using the MediaMetadataRetriever to extract them, but the retriever is unable to extract the metadata for most of the songs (~630 of 669). In my PC music software, the metadata are visible and in the Windows Explorer as well. If I open the properties of the songs, I can modify them and if I load the changed files on the phone, it still doesn't work. By the way: If I use any other player on the phone, it is always able to load the metadata.
Is the MediaMetadataRetriever buggy and should I use some other libraries for extracting or am I doing something wrong?
This question is related, but doesn't really help to solve my problem.
Here is some of my code as an example:
MediaMetadataRetriever lMetaData = new MediaMetadataRetriever();
lMetaData.setDataSource(mAbsolutePath);
mArtist = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
mTitle = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
mAlbum = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
mAlbumArtist = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
mGenre = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
mSongNumber = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);
mYear = lMetaData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
if(mArtist == null)
mArtist = new String("");
if(mTitle == null)
mTitle = new String("");
if(mAlbum == null)
mAlbum = new String("");
if(mAlbumArtist == null)
mAlbumArtist = new String("");
if(mGenre == null)
mGenre = new String("");
if(mSongNumber == null)
mSongNumber = new String("");
if(mYear == null)
mYear = new String("");
MediaMetadataRetriever only supports a handful of formats. I recommend FFmpegMediaMetadataRetriever. It supports several additional formats and protocols.