Youtube C# .NET API : Uploading video and getting events when finished - c#

This is the code to upload a video to Youtube using the C# .NET API from a Windows Forms desktop application:
YouTubeRequestSettings settings = new YouTubeRequestSettings("whatwill come here ?",
"my api key",
"my youtube login email", "my youtube login password");
YouTubeRequest request = new YouTubeRequest(settings);
Video newVideo = new Video();
newVideo.Title = "test 1";
newVideo.Tags.Add(new MediaCategory("Gaming", YouTubeNameTable.CategorySchema));
newVideo.Keywords = "test 1 , test 2";
newVideo.Description = "test 3 test 4";
newVideo.YouTubeEntry.Private = false;
newVideo.Tags.Add(new MediaCategory("tag 1, tag 2",
YouTubeNameTable.DeveloperTagSchema));
newVideo.YouTubeEntry.Location = new GeoRssWhere(37, -122);
newVideo.YouTubeEntry.MediaSource = new MediaFileSource("C:\\test.avi", "video/quicktime");
Video createdVideo = request.Upload(newVideo);
This works. What I'm looking for is the events that get me back the upload progress, so I can show the progress in a progressbar. Ich can register the following events:
request.Service.AsyncOperationProgress +=
new AsyncOperationProgressEventHandler(Service_AsyncOperationProgress);
request.Service.AsyncOperationCompleted +=
new AsyncOperationCompletedEventHandler(Service_AsyncOperationCompleted);
... but they never get fired while uploading. Also, I cannot find any documentation about the .NET api that goes much further than the small video upload example above. So: Are those the wrong events to look for? Just for reference, I'm starting the seemingly synchonous upload in the following code in a background thread:
ThreadPool.QueueUserWorkItem(
delegate
{
try
{
createdVideo = request.Upload(newVideo);
} catch (Exception ex){
Invoke((ThreadStart) delegate{uploadingFailedWithException(ex);});
}
});
Invoke((ThreadStart)readyUploading);
This way I know when the synchonous operation ended, but I'd like to have events for progress updates to the user. Any ideas?

The Upload method you are using is synchronous and, as such, the execution of your program will stop on that line of code and only move on when the upload is complete.
What you are trying to do requires using asynchronous upload. A complete example showing how to use the ResumableUploader component and the AsyncOperationCompleted/AsyncOperationProgress events is included in the .NET client library and available at http://code.google.com/p/google-gdata/source/browse/#svn%2Ftrunk%2Fclients%2Fcs%2Fsamples%2FYouTubeUploader%2FYouTubeUploader

Related

Android Notification Sound Causes Media Volume to Duck (Lower) & It Never Comes Back

I just converted one of my apps to target Android API 9 (was targeting API 8); now when notifications are sent out, the volume of media is lowered and never comes back to full volume.
The app uses WebView to play media files. This was not happening prior to targeting API 9. I had to convert the app into level 9 so that I could upload to the Google Play Store. I am running a Samsung S7 which was originally designed for API level 6 (with the OS upgraded to 8.0), not sure if that has something to do with the issue. Another detail is that I use Xamarin.Android for development, not sure if that matters either.
Additionally, I forced the notifications to play a blank sound (a very short[couple ms] blank mp3) in the same build that I converted the app to target API 9:
var channelSilent = new Android.App.NotificationChannel(CHANNEL_ID, name + " Silent", Android.App.NotificationImportance.High)
{
Description = description
};
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build()
//blank is blank mp3 file with nothing in it, a few ms in duration
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3")
channelSilent.SetSound(uri, alarmAttributes);
...so it could also be the blank sound that is causing the ducking to malfunction, not the API change. Is there something to do with notification sound ducking that could be causing the issue? Is there any other way to mute a notification with Xamarin.Android other than playing a blank sound? That is one route I think would be worth trying to fix this issue.
Here is the code I am using to generate notifications:
private static List<CustomNotification> _sentNotificationList = new List<CustomNotification>();
private static NotificationManagerCompat _notificationManager;
public async void SendNotifications(List<CustomNotification> notificationList)
{
await Task.Run(() =>
{
try
{
var _ctx = Android.App.Application.Context;
if (_notificationManager == null)
{
_notificationManager = Android.Support.V4.App.NotificationManagerCompat.From(_ctx);
}
if (notificationList.Count == 0)
{
return;
}
int notePos = 0;
foreach (var note in notificationList)
{
var resultIntent = new Intent(_ctx, typeof(MainActivity));
var valuesForActivity = new Bundle();
valuesForActivity.PutInt(MainActivity.COUNT_KEY, _count);
valuesForActivity.PutString("URL", note._noteLink);
resultIntent.PutExtras(valuesForActivity);
var resultPendingIntent = PendingIntent.GetActivity(_ctx, MainActivity.NOTIFICATION_ID, resultIntent, PendingIntentFlags.UpdateCurrent);
resultIntent.AddFlags(ActivityFlags.SingleTop);
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build();
//I am playing this blank sound to prevent android from spamming sounds as the notifications get sent out
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3");
//if the notification is the first in our batch then use this
//code block to send the notifications with sound
if (!_sentNotificationList.Contains(note) && notePos == 0)
{
var builder = new Android.Support.V4.App.NotificationCompat.Builder(_ctx, MainActivity.CHANNEL_ID + 1)
.SetAutoCancel(true)
.SetContentIntent(resultPendingIntent) // Start up this activity when the user clicks the intent.
.SetContentTitle(note._noteText) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.bitchute_notification2)
.SetContentText(note._noteType)
.SetPriority(NotificationCompat.PriorityMin);
MainActivity.NOTIFICATION_ID++;
_notificationManager.Notify(MainActivity.NOTIFICATION_ID, builder.Build());
_sentNotificationList.Add(note);
notePos++;
}
//if the notification isn't the first in our batch, then use this
//code block to send the notifications without sound
else if (!_sentNotificationList.Contains(note))
{
var builder = new Android.Support.V4.App.NotificationCompat.Builder(_ctx, MainActivity.CHANNEL_ID)
.SetAutoCancel(true) // Dismiss the notification from the notification area when the user clicks on it
.SetContentIntent(resultPendingIntent) // Start up this activity when the user clicks the intent.
.SetContentTitle(note._noteText) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.bitchute_notification2)
.SetContentText(note._noteType)
.SetPriority(NotificationCompat.PriorityHigh);
MainActivity.NOTIFICATION_ID++;
_notificationManager.Notify(MainActivity.NOTIFICATION_ID, builder.Build());
_sentNotificationList.Add(note);
notePos++;
}
ExtStickyService._notificationsHaveBeenSent = true;
}
}
catch
{
}
});
}
In my MainActivity I've created two different notification channels: one is silent; the other uses default notification setting for the device:
void CreateNotificationChannel()
{
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build();
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3");
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var name = "BitChute";
var description = "BitChute for Android";
var channelSilent = new Android.App.NotificationChannel(CHANNEL_ID, name + " Silent", Android.App.NotificationImportance.High)
{
Description = description
};
var channel = new Android.App.NotificationChannel(CHANNEL_ID + 1, name, Android.App.NotificationImportance.High)
{
Description = description
};
channel.LockscreenVisibility = NotificationVisibility.Private;
//here is where I set the sound for the silent channel... this could be the issue?
var notificationManager = (Android.App.NotificationManager)GetSystemService(NotificationService);
channelSilent.SetSound(uri, alarmAttributes);
notificationManager.CreateNotificationChannel(channel);
notificationManager.CreateNotificationChannel(channelSilent);
}
Full source: https://github.com/hexag0d/BitChute_Mobile_Android_BottomNav/tree/APILevel9
EDIT: something really interesting is that if I pulldown the system ui bar, the volume goes back to normal. Very strange workaround but it might help diagnose the cause.
DOUBLE EDIT: I used .SetSound(null, null) instead of using the blank .mp3 and the ducking works fine now. See comments

AWS - Amazon Polly Text To Speech

I have doubts about the "text-to-speech" Amazon Polly service.
I've integrated this service in my chatbot, in order to describe vocally what the bot writes to the user in chat.
It works pretty well, but I don't know if it is possible to stop the voice early, before she (I chose a female voice) finishes speaking. Sometimes I need to go further in the conversation and I don't want to listen until the end of the sentence.
This is the code used for the integration:
//Html side
function textToSpeech(text) {
$.ajax({
type: 'GET',
url: '/Chat/TextToSpeech?text=' + text,
cache: false,
success: function (result) {
var audio = document.getElementById('botvoice');
$("#botvoice").attr("src", "/Audios/" + result);
audio.load();
audio.play();
}
});
}
Controller side:
public ActionResult TextToSpeech(string text)
{
string filename = "";
try
{
AWSCredentials credentials = new StoredProfileAWSCredentials("my_credential");
AmazonPollyClient client = new AmazonPollyClient(credentials, Amazon.RegionEndpoint.EUWest1);
// Create describe voices request.
DescribeVoicesRequest describeVoicesRequest = new DescribeVoicesRequest();
// Synchronously ask Amazon Polly to describe available TTS voices.
DescribeVoicesResponse describeVoicesResult = client.DescribeVoices(describeVoicesRequest);
List<Voice> voices = describeVoicesResult.Voices;
// Create speech synthesis request.
SynthesizeSpeechRequest synthesizeSpeechPresignRequest = new SynthesizeSpeechRequest();
// Text
synthesizeSpeechPresignRequest.Text = text;
// Select voice for synthesis.
synthesizeSpeechPresignRequest.VoiceId = voices[18].Id;
// Set format to MP3.
synthesizeSpeechPresignRequest.OutputFormat = OutputFormat.Mp3;
// Get the presigned URL for synthesized speech audio stream.
string current_dir = AppDomain.CurrentDomain.BaseDirectory;
filename = CalculateMD5Hash(text) + ".mp3";
var path_audio = current_dir + #"\Audios\" + filename;
var presignedSynthesizeSpeechUrl = client.SynthesizeSpeechAsync(synthesizeSpeechPresignRequest).GetAwaiter().GetResult();
FileStream wFile = new FileStream(path_audio, FileMode.Create);
presignedSynthesizeSpeechUrl.AudioStream.CopyTo(wFile);
wFile.Close();
}
catch (Exception ex)
{
filename = ex.ToString();
}
return Json(filename, JsonRequestBehavior.AllowGet);
}
An input text is present in my chat (obviously) for writing and sending (by pressing ENTER on the keyboard) the question to the bot. I tried to put the command audio.src="" in the handler, and she stops to talk but the chat still remains blocked... It seems like it waits the end of the audio stream. I have to refresh the page to see new messages and responses.
Is there any Amazon function that I can call with a particular parameter set, in order to notify the service that I want to stop and clear the audio stream?
Amazon Polly returns a .mp3 file. It is not responsible for playing the audio file.
Any difficulties you are experiencing playing/stopping the audio would be the result of the code you are using to play an MP3 audio file. It has nothing to do with the Amazon Polly service itself.
Thank you! I found the real problem: when I stopped the audio I didn't print the rest of the messages. I add the call to the function that print messages on the chat. For stopping the voice I used the command audio.src="";

Download file from opensubtitles.org

I need to download files from opensubtitles.org trough my application which is written in GTK# and C#. The app is based on .NET 4.0 framework.
At first this was the code I was using:
var tZip = new FastZip();
try {
var tRequest = (HttpWebRequest)HttpWebRequest.Create(tDownloadUrl);
var tZipResponse = (HttpWebResponse)tRequest.GetResponse();
using (var tStream = tZipResponse.GetResponseStream()) {
using (var tMemStream = new MemoryStream()) {
tStream.CopyTo(tMemStream);
var tTempPath = Globals.video_location + "OSD";
Directory.CreateDirectory(tTempPath);
tZip.ExtractZip(tMemStream, tTempPath, FastZip.Overwrite.Always, null, #"\.srt$", null, false, true);
var tDirInfo = new DirectoryInfo(tTempPath);
var tFileInfo = new FileInfo(Globals.location_video);
var tSrtFile = tDirInfo.EnumerateFiles().FirstOrDefault();
if (tSrtFile == null) {
writeLog("No .srt file found in zip..");
goto text;
}
writeLog("Downloaded and unpacked: " + tSrtFile.Name);
File.Copy(tSrtFile.FullName, Globals.video_location+Globals.video_name+".srt", true);
Globals.savedTitle = Globals.video_location+Globals.video_name+".srt";
// clean up..
Directory.Delete(tTempPath, true);
writeLog("Deleted temp folder.");
return true;
}
}}
And that worked really well up until few days ago, now it is returning a bunch of html code instead of .zip file. I tried even something like this:
WebClient client = new WebClient();
client.DownloadFile(link, #"OSD\test.zip");
But everything just keeps returning bunch of html code.
The link I am usually trying to download is something like this:
http://dl.opensubtitles.org/en/download/subad/4287952
If you click on the link above it will just redirect you to the opensubtitles.org page of that particular subtitle. But if you right mouse click on that link and then select "open in new tab" or "open in new window" it will automatically start the download. (Tested in Firefox)
Also as soon as I paste that link in "Internet Download Manager" application, it will start the download of the zip file automatically.
If you can help me to resolve this problem I will truly be grateful.
Kind Regards.
I got into this problem because I was filtering the website xml directly. Like from a link such as this one: opensubtitles.org example
And in the beginning it used to work well, but then they changed something on the website and it stopped working. So what I did was build on top of this: OSHandler
That handler library is using XML-RPC so I believe there won't be any problems in the future.

YouTube C# API - How do I resume a failed upload

I'm trying to upload large video files to youtube via the C# API using the ResumableUploader
The code looks like this:
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
settings.Timeout = int.MaxValue;
var newVideo = new Video();
newVideo.Title = title.Trim();
newVideo.Tags.Add(new MediaCategory("Games", YouTubeNameTable.CategorySchema));
newVideo.Keywords = keywords;
newVideo.Description = description;
newVideo.YouTubeEntry.Private = false;
newVideo.Tags.Add(new MediaCategory("StarCraft2, Replay", YouTubeNameTable.DeveloperTagSchema));
var contentType = MediaFileSource.GetContentTypeForFileName(filePathToUpload);
newVideo.YouTubeEntry.MediaSource = new MediaFileSource(filePathToUpload, contentType);
var link = new AtomLink("http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads");
link.Rel = ResumableUploader.CreateMediaRelation;
newVideo.YouTubeEntry.Links.Add(link);
var resumableUploader = new ResumableUploader(256); //chunksize 256 kilobyte
resumableUploader.AsyncOperationCompleted += resumableUploader_AsyncOperationCompleted;
resumableUploader.AsyncOperationProgress += resumableUploader_AsyncOperationProgress;
var youTubeAuthenticator = new ClientLoginAuthenticator(Configuration.YouTubeApplicationName, ServiceNames.YouTube, Configuration.YouTubeUsername, Configuration.YouTubePassword);
youTubeAuthenticator.DeveloperKey = Configuration.YouTubeApplicationKey;
resumableUploader.InsertAsync(youTubeAuthenticator, newVideo.YouTubeEntry, new object());
I try to get the video ID when the async opertion is finished like this:
private static void resumableUploader_AsyncOperationCompleted(object sender, AsyncOperationCompletedEventArgs e)
{
try
{
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
var request = new YouTubeRequest(settings);
Video v = request.ParseVideo(e.ResponseStream);
}
catch (Exception ex)
{
//Upload has been disturbed.
}
}
The problem is. Sometime there is a problem with the upload, shaky connection or stuff like that. When an error occurs AsyncOperationCompleted is getting called.
Now the question is. How do I resume the upload? I can get the current position via the AsyncOperationProgress event. But how do I proceed to continue the upload?
I know this is an old question but I found it while trying to do the same thing with V3 of the YouTube API. This looks like code from an earlier version of the API so my question asking the same thing for V3 of the API may help if you upgrade.
I've pasted some older code of mine if anyone is struggling with this but I'm switching to the new version and replacing all this code. The youtube_upload object is my own rolled class and not part of the api. I'm also using ReSharper now and following their naming conventions.
//Grab the rendered YouTube video ready for upload
string content_type = MediaFileSource.GetContentTypeForFileName(youtube_upload.YouTubeFileName);
MediaFileSource media_file_source = new MediaFileSource(youtube_upload.YouTubeFileName, content_type);
//Generate a media stream and move to the currently uploaded position within it
media_stream_resume = media_file_source.GetDataStream();
media_stream_resume.Seek(youtube_upload.CurrentPosition, SeekOrigin.Begin);
youtube_uploading_id = youtube_upload.YouTubeID;
//Attempt to resume the upload
resumable_uploader.ResumeAsync(youtube_authenticator, youtube_upload.ResumeUri,
youtube_upload.httpVerb, media_stream_resume, content_type, youtube_upload);
youtube_upload.ErrorText = Constants.YouTubeStatusResuming;
youtube_upload.SaveYouTube();

Uploading Any File To Google Docs Using GData

I'm trying to use the Google Docs GData API (.NET) to upload a file to my docs, but I keep getting errors thrown. I can't find any example that uses this method, so I'm not even sure that I am usign it correctly.
DocumentsService docService = new DocumentsService("MyDocsTest");
docService.setUserCredentials("w****", "*****");
DocumentsListQuery docQuery = new DocumentsListQuery();
DocumentsFeed docFeed = docService.Query(docQuery);
foreach (DocumentEntry entry in docFeed.Entries)
{
Console.WriteLine(entry.Title.Text);
}
Console.ReadKey();
Console.WriteLine();
if (File.Exists(#"testDoc.txt") == false)
{
File.WriteAllText(#"testDoc.txt", "test");
}
docService.UploadDocument(#"testDoc.txt", null); // Works Fine
docService.UploadFile(#"testDoc.txt", null, #"text/plain", false); // Throws Error
The above code will throw a GDataRequestException:
Execution of request failed: https://docs.google.com/feeds/default/private/full?convert=false
This is kind of aggrivating, seeing as this API could be so insanely helpful. Does anyone know what I am doing wrong?
After a lot of experimentation and research, I got it to work. Gonna leave this here for others in my predicament. I will leave in the using shorthands for reference.
// Start the service and set credentials
Docs.DocumentsService service = new Docs.DocumentsService("GoogleApiTest");
service.setUserCredentials("username", "password");
// Initialize the DocumentEntry
Docs.DocumentEntry newEntry = new Docs.DocumentEntry();
newEntry.Title = new Client.AtomTextConstruct(Client.AtomTextConstructElementType.Title, "Test Upload"); // Set the title
newEntry.Summary = new Client.AtomTextConstruct(Client.AtomTextConstructElementType.Summary ,"A summary goes here."); // Set the summary
newEntry.Authors.Add(new Client.AtomPerson(Client.AtomPersonType.Author, "A Person")); // Add a main author
newEntry.Contributors.Add(new Client.AtomPerson(Client.AtomPersonType.Contributor, "Another Person")); // Add a contributor
newEntry.MediaSource = new Client.MediaFileSource("testDoc.txt", "text/plain"); // The actual file to be uploading
// Create an authenticator
Client.ClientLoginAuthenticator authenticator = new Client.ClientLoginAuthenticator("GoogleApiTest", Client.ServiceNames.Documents, service.Credentials);
// Setup the uploader
Client.ResumableUpload.ResumableUploader uploader = new Client.ResumableUpload.ResumableUploader(512);
uploader.AsyncOperationProgress += (object sender, Client.AsyncOperationProgressEventArgs e) =>
{
Console.WriteLine(e.ProgressPercentage + "%"); // Progress updates
};
uploader.AsyncOperationCompleted += (object sender, Client.AsyncOperationCompletedEventArgs e) =>
{
Console.WriteLine("Upload Complete!"); // Progress Completion Notification
};
Uri uploadUri = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false"); // "?convert=false" makes the doc be just a file
Client.AtomLink link = new Client.AtomLink(uploadUri.AbsoluteUri);
link.Rel = Client.ResumableUpload.ResumableUploader.CreateMediaRelation;
newEntry.Links.Add(link);
uploader.InsertAsync(authenticator, newEntry, new object()); // Finally upload the bloody thing
Can you check the ResponseString property of the GDataRequestException that is being thrown in order to get a detailed error message?
Capturing your requests with a tool like Fiddler will also help you a lot when trying to debug this kind of issues.

Categories

Resources