chef 3745 Posted November 18, 2019 Share Posted November 18, 2019 I was just messing around with Alexa's personalized responses. Yeah she can figure out who is speaking to her. More information here: https://developer.amazon.com/docs/custom-skills/add-personalized-greetings-or-prompts.html Here is my Alexa response for Emby custom Skill, notice the Person object: using System; using System.Collections.Generic; namespace AlexaController.Alexa { public class AlexaRequest { public Session session { get; set; } public Request request { get; set; } public Context context { get; set; } public string version { get; set; } } public class Application { public string applicationId { get; set; } } public class Attributes { public string key { get; set; } } public class Permissions { public string consentToken { get; set; } } public class User { public string userId { get; set; } public string accessToken { get; set; } public Permissions permissions { get; set; } } public class Session { public bool @[member="new"] { get; set; } public string sessionId { get; set; } public Application application { get; set; } public Attributes attributes { get; set; } public User user { get; set; } } public class AudioPlayer { } public class SupportedInterfaces { public AudioPlayer AudioPlayer { get; set; } } public class Device { public string deviceId { get; set; } public SupportedInterfaces supportedInterfaces { get; set; } } public class Application2 { public string applicationId { get; set; } } public class Permissions2 { public string consentToken { get; set; } } public class User2 { public string userId { get; set; } public string accessToken { get; set; } public Permissions2 permissions { get; set; } } public class Person //right here { public string personId { get; set; } public string accessToken { get; set; } } public class System { public Device device { get; set; } public Application2 application { get; set; } public User2 user { get; set; } public Person person { get; set; } public string apiEndpoint { get; set; } public string apiAccessToken { get; set; } } public class AudioPlayer2 { public string playerActivity { get; set; } public string token { get; set; } public int offsetInMilliseconds { get; set; } } public class Context { public System System { get; set; } public AudioPlayer2 AudioPlayer { get; set; } } public class Intent { public string name { get; set; } public string confirmationStatus { get; set; } public Slots slots { get; set; } } public class Request { public string type { get; set; } public string requestId { get; set; } public DateTime timestamp { get; set; } public string locale { get; set; } public Intent intent { get; set; } } public class Slots { //public slotData MediaName { get; set; } public slotData SeriesName { get; set; } public slotData Username { get; set; } public slotData MusicGroup { get; set; } public slotData MusicAlbum { get; set; } public slotData MovieNames { get; set; } public slotData PlayToDevice { get; set; } public slotData DeviceNames { get; set; } public slotData DeviceRooms { get; set; } } public class slotData { public string name { get; set; } public string value { get; set; } } public class Error { public string type { get; set; } public string message { get; set; } } } Now in the Emby endpoint: //Most important parts of this class is the 'person' object, and the Id // Then using conditions to return '<alexa:name type="first personId="{personId}" /> The first name of the recognized User. using System; using System.Collections.Generic; using System.Linq; using System.Threading; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Services; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Entities; using System.IO; using AlexaController.Alexa; using MediaBrowser.Model.Serialization; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Session; using System.Threading.Tasks; using System.Text; using System.Net; using System.Text.RegularExpressions; using Person = AlexaController.Alexa.Person; namespace AlexaController.API { [Route("/Alexa", "POST", Summary = "Alexa End Point")] public class AlexaRequest: IRequiresRequestStream { public Stream RequestStream { get; set; } } [Route("/Alexa", "GET", Summary = "Alexa End Point")] public class Test : IReturnVoid { public Stream test { get; set; } } public class AlexaApi : IService { private readonly ILogger logger; //private ITVSeriesManager TvSeriesManager { get; set; } private IUserManager UserManager { get; } //private IMediaSourceManager MediaSourceManager { get; set; } private ILibraryManager LibraryManager { get; } //private IHttpClient HttpClient { get; set; } private ISessionManager SessionManager { get; } private IJsonSerializer JsonSerializer { get; } private IUserDataManager UserDataManager { get; } // The media item we want to play private static BaseItem RequestedMediaItem; //Was a playback Request private static bool IsPlaybackRequest; private static bool ResumeMedia; // ReSharper disable once TooManyDependencies public AlexaApi(ILibraryManager libraryManager, ISessionManager sessionManager, ILogManager logManager, IUserManager userManager, IJsonSerializer json, IUserDataManager userData) { logger = logManager.GetLogger(GetType().Name); //TvSeriesManager = tvSeriesManager; //MediaSourceManager = mediaSourceManager; SessionManager = sessionManager; LibraryManager = libraryManager; UserManager = userManager; //HttpClient = httpClient; JsonSerializer = json; UserDataManager = userData; } // ReSharper disable once MethodNameNotMeaningful public string Get(Test test) { return "Hello World Yes you can all see this"; } public object Post(AlexaRequest request) { //parse json request var alexaRequest = JsonSerializer.DeserializeFromStream<Alexa.AlexaRequest>(request.RequestStream); // ReSharper disable once TooManyChainedReferences var person = alexaRequest.context.System.person ?? null; //<--I am a person object that might not return anything for privacy reasons logger.Debug("ALEXA HERE"); var r = alexaRequest.request; switch (r.type) { case "IntentRequest": PostDirectiveResponseAsync(alexaRequest); //<--I can post a directive response switch (r.intent.name) { case "AMAZON.NavigateHomeIntent": BrowseHome("family room"); return BuildAlexaResponse("OK. Here is the Home Screen"); case "ShowCollectionLibrary": { RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("Collections")); BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("Collections"))); return BuildAlexaResponse("Here is the Collections Library."); } case "ShowTVLibrary": { RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("TV Shows")); BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("TV Shows"))); return BuildAlexaResponse("Here is the TV Series Library."); } case "ShowMovieLibrary": { RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("Movies")); BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("Movies"))); return BuildAlexaResponse("Here is the Movie Library."); } case "DeviceChoice": { var str = r.intent.slots.DeviceNames.value ?? r.intent.slots.DeviceRooms.value; if (r.intent.slots.DeviceNames == null) { return " Sorry no device by that name was found"; } //PlayMediaItemAsync(str, RequestedMediaItem.MediaType); return BuildAlexaResponse("OK"); } case "NewMovies": { return BuildAlexaResponse(GetNewMovies(), true.ToString(), person); } case "NewTV": { return BuildAlexaResponse(GetNewTvNames()); } case "AMAZON.PauseIntent": { return RemoteChangeState(PlaystateCommand.Pause, "family room"); } case "AMAZON.ResumeIntent": { return RemoteChangeState(PlaystateCommand.Unpause, "family room"); } case "remoteSkip": { return RemoteChangeState(PlaystateCommand.NextTrack, "family room"); } case "remotePrevious": { return RemoteChangeState(PlaystateCommand.PreviousTrack, "family room"); } case "remoteStop": { return RemoteChangeState(PlaystateCommand.Stop, "family room"); } case "AMAZON.NoIntent": { if (!IsPlaybackRequest) return BuildAlexaResponse("I'm not sure what you are saying \"no\" to. Sorry"); ResumeMedia = false; IsPlaybackRequest = false; PlayMediaItemAsync("family room", RequestedMediaItem); return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + " Now playing the " + RequestedMediaItem.ProductionYear + " film <break strength='weak' />" + RequestedMediaItem.Name.Replace(":", string.Empty) .Replace(",", string.Empty)); } case "AMAZON.YesIntent": { if (!IsPlaybackRequest) return BuildAlexaResponse("I'm not sure I understand what you are agreeing to. Sorry"); ResumeMedia = true; IsPlaybackRequest = false; PlayMediaItemAsync("family room", RequestedMediaItem); return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + " Now playing the " + RequestedMediaItem.ProductionYear + " " + RequestedMediaItem.MediaType + " <break strength='weak' />" + RequestedMediaItem.Name.Replace(":", string.Empty) .Replace(",", string.Empty)); } case "AMAZON.CancelIntent": case "AMAZON.StopIntent": return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + "Canceling."); case "PlayMovie": { try { RequestedMediaItem = NarrowResults(r.intent.slots.MovieNames.value, new[] { "Movie" }); IsPlaybackRequest = true; if (RequestedMediaItem.SupportsPositionTicksResume) { return BuildAlexaResponse(RequestedMediaItem.Name + " is bookmarked. " + AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) + "Would you like to play the Movie from where you left off?", "false", person); } else { return BuildAlexaResponse(" in what room would you like to watch " + RequestedMediaItem.Name.Replace(":", string.Empty), "false"); } } catch (Exception) { return BuildAlexaResponse("Sorry. I couldn't find " + r.intent.slots.MovieNames.value + " in the library"); } } case "BrowseCommand": { //The type of media we want to search for - We'll expect a Movie name to start var type = "Movie"; //Amazon will return a Movie slot if it is a movie name var searchName = r.intent.slots.MovieNames.value; //If no Movie Name it must be a series Name if(r.intent.slots.MovieNames.value == null) { searchName = r.intent.slots.SeriesName.value; type = "Series"; } try { var result = NarrowResults(searchName, new[] { type }); if (result != null) { RequestedMediaItem = result; IsPlaybackRequest = false; BrowseItemAsync("family room", result); string overview = ""; string rating = ""; float? criticRating; overview = RequestedMediaItem.Overview; rating = RequestedMediaItem.OfficialRating; criticRating = RequestedMediaItem.CriticRating; return BuildAlexaResponse(" Here is the details for " + RequestedMediaItem.Name.Replace(":", string.Empty) + ". " + AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) + "Rated " + rating + "." + AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.strong) + CalculateCriticRatings(criticRating), true.ToString(), person); } } catch (Exception) { return BuildAlexaResponse("Sorry. I couldn't find " + searchName + " in the library"); } return BuildAlexaResponse("Sorry. I couldn't find " + searchName + " in the library"); } default: return BuildAlexaResponse("no intent found"); } case "SessionEndedRequest": //Session End Request //No response message is allowed return null; case "LaunchRequest": return BuildAlexaResponse("Welcome"); //Not an Intent default: return BuildAlexaResponse("Unknown"); } } private string GetLibraryId(string type) { var results = LibraryManager.GetVirtualFolders(); foreach(var item in results) { if(item.Name == type) { return item.ItemId; } } return string.Empty; } private string GetNewMovies() { const string user = "Admin"; var results = LibraryManager.GetItemIds(new InternalItemsQuery { IncludeItemTypes = new[] { "Movie" }, IsPlayed = false, User = UserManager.GetUserByName(user.AsSpan()) }); string alexaSpeechString = string.Empty; var listOfNewMovies = new List<BaseItem>(); results.ToList().ForEach(item => { var itemInfo = LibraryManager.GetItemById(item); if (itemInfo.DateCreated >= DateTime.Now.AddDays(-25)) { listOfNewMovies.Add(itemInfo); } }); //If the movie is the last name in the list, let Alexa say "and also". She sounds more human. int movieCount = 0; foreach (var movie in listOfNewMovies) { if (movieCount == listOfNewMovies.Count - 1) { alexaSpeechString += " and also <break strength='weak' /> "; } alexaSpeechString += movie.Name.Replace(":", string.Empty).Replace("&", "and") + "<break strength='weak' />. "; //She doesn't like '&' and ':' in strings movieCount += 1; } return "Here are <say-as interpret-as='cardinal'>" + movieCount + "</say-as> of the newest movies available in the library <break strength='weak' />" + alexaSpeechString; } private string GetNewTvNames() { var results = LibraryManager.GetItemIds(new InternalItemsQuery { IncludeItemTypes = new[] { "Episode" } }); string str1 = string.Empty; string complete; int tvCount = 0; var listOfNewTv = new List<string>(); results.ToList().ForEach(item => { var itemInfo = LibraryManager.GetItemById(item); if (itemInfo.DateCreated >= DateTime.Now.AddDays(-20)) { listOfNewTv.Add(itemInfo.Parent.Parent.Name); //That would be the Series Name } }); if (listOfNewTv.Count == 0) { complete = "There are no new unwatched episodes"; } else { var distinctTvSeries = listOfNewTv.Distinct().ToList(); foreach (var name in distinctTvSeries) { //If the tv is the last name in the list, let Alexa say "and also". She sounds more human. if (tvCount == distinctTvSeries.Count - 1) { str1 += " and also <break strength='weak' />"; } str1 += name.Replace(":", string.Empty).Replace("&", "and") + "<break strength='weak' />"; tvCount += 1; } complete = "There are <say-as interpret-as='cardinal'>" + listOfNewTv.Distinct().ToList().Count + "</say-as> new episodes available in the library <break strength='weak' />" + "including episodes from <break strength='weak' />" + str1; } return complete; } private string GetDeviceIdFromName(string deviceName) { if (deviceName.ToLower().Contains("family room") || deviceName.ToLower().Contains("front room")) { deviceName = "Family Room Fire TV Stick"; } else if (deviceName.ToLower().Contains("back room") || deviceName.ToLower().Contains("kids")) { deviceName = "Kids TV"; } else if (deviceName.ToLower().Contains("bedroom") || deviceName.ToLower().Contains("upstairs")) { deviceName = "Chromecast0862"; } else if (deviceName.ToLower().Contains("theater") || deviceName.ToLower().Contains("movie theater")) { deviceName = "CastP6"; } foreach (var session in SessionManager.Sessions) { //If it is a browse request then we'll have have to use an emby app with a UI display to show the details //example: Emby Theater if (session.Client.ToLower().Contains("androidtv") && deviceName == "Family Room Fire TV Stick") { return session.DeviceId; } if (session.DeviceName.ToLower().Contains(deviceName.ToLower())) { return session.DeviceId; } if (session.Client.ToLower().Contains(deviceName.ToLower())) { return session.DeviceId; } } return string.Empty; } private SessionInfo GetSession(string deviceId) { //logger.Info("Looking for sessions for device " + deviceId); var r = SessionManager.Sessions.Where(i => i.DeviceId == deviceId); // "db464421188f5622f73acab7252660facbd63078"); var sessionInfos = r.ToList(); logger.Info("Found {0} sessions for device {1}", sessionInfos.Count().ToString(), deviceId); return sessionInfos.FirstOrDefault(); } private void BrowseHome(string device) { var d = GetDeviceIdFromName(device); var user = "Admin"; var s = GetSession(d); //DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT SessionManager.SendGeneralCommand(null, s.Id, new GeneralCommand() { Name = "GoHome", ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString(), }, CancellationToken.None); } private void BrowseItemAsync(string device, BaseItem request) { try { var d = GetDeviceIdFromName(device); var s = GetSession(d); ////DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT //SessionManager.SendGeneralCommand(null, s.Id, new GeneralCommand() //{ // Name = "GoHome", // ControllingUserId = UserManager.GetUserByName("Admin").Id.ToString() //}, // CancellationToken.None); Task.Delay(1500).Wait(); SessionManager.SendBrowseCommand(null, s.Id, new BrowseRequest() { ItemId = request.Id.ToString(), ItemName = request.Name, ItemType = request.MediaType }, CancellationToken.None); } catch { BuildAlexaResponse("I'm sorry. I'm unable to show details for " + RequestedMediaItem.Name.Replace(":", string.Empty) + " in the family room because the theater is not currently running."); } } private async void PlayMediaItemAsync(string device, BaseItem request) { var s = GetSession(GetDeviceIdFromName(device)); if (s == null) return;// "I'm sorry the " + device + " device is currently unavailable."; long startTicks = 0; var user = "Admin"; if (ResumeMedia) { startTicks = UserDataManager.GetUserData(UserManager.GetUserByName(user.AsSpan()).Id.ToString(), RequestedMediaItem).PlaybackPositionTicks; } SessionManager.SendPlayCommand(null, s.Id, new PlayRequest { StartPositionTicks = startTicks, PlayCommand = PlayCommand.PlayNow, ItemIds = new[] { request.InternalId }, ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString() }, CancellationToken.None); } private async Task<string> RemoteChangeState(PlaystateCommand psCmd, string device) { var d = GetDeviceIdFromName(device); var s = GetSession(d); var user = "Admin"; if (s == null) { return "device is not setup or is unavailable"; } var command = new PlaystateRequest() { Command = psCmd, ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString() }; try { //DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT SessionManager.SendPlaystateCommand(null, s.Id, command, new CancellationToken(false)); } catch { } return BuildAlexaResponse("ok"); } public string GetSeriesId(string seriesName) { var r = LibraryManager.GetItemIds(new InternalItemsQuery { IncludeItemTypes = new[] { "Series" }, Name = seriesName }); return r.Any() ? r.FirstOrDefault().ToString() : ""; } //Actual Response private string BuildAlexaResponse(string text, string sessionEnd = "true", Person person = null) { var jsonString = "{\"version\": \"1.0\",\"response\": {\"outputSpeech\": {\"type\": \"SSML\",\"ssml\": "; jsonString += "\"<speak>"; jsonString += AlexaOptions.HumanizeAlexa(); // ReSharper disable ComplexConditionExpression jsonString += person != null ? " <alexa:name type='first' personId='" + person.personId + "'/> " : " "; jsonString += AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.strong); jsonString += " "; jsonString += text; jsonString += "</speak>\" }, \"shouldEndSession\": "; jsonString += sessionEnd + "},\"sessionAttributes\": { } }"; logger.Log(LogSeverity.Debug, jsonString); return jsonString; } private void PostDirectiveResponseAsync(Alexa.AlexaRequest alexaRequest) { //const string uri = "https://api.amazonalexa.com/v1/directives"; var res = new DirectiveResponse { header = new Header { requestId = alexaRequest.request.requestId }, directive = new Directive { type = "VoicePlayer.Speak", speech = "<speak>" + AlexaOptions.HumanizeAlexa() + "Accessing Media Server." + AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) + " One moment please." + "<audio src='https://s3.amazonaws.com/ask-soundlibrary/scifi/amzn_sfx_scifi_radar_high_ping_01.mp3'/></speak>" } }; string json = JsonSerializer.SerializeToString(res); //Encode the JSON string into a byte array byte[] data = Encoding.ASCII.GetBytes(json); //Where we will send the info and how: POST var request = (HttpWebRequest)WebRequest.Create("https://api.amazonalexa.com/v1/directives"); request.Method = "POST"; request.ContentType = "application/json"; request.Headers["Authorization"] = "Bearer " + alexaRequest.context.System.apiAccessToken; request.ContentLength = data.Length; //Write the data to amazon using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } } private static string CalculateCriticRatings(float? percent) { if (percent <= 25.0F) { return "This film didn't get great reviews."; } else if (percent <= 50.0F) { return "This film has got some fair reviews."; } else if (percent <= 75.0F) { return "This film has got some decent reviews."; } else if (percent <= 90.0F) { return "This film has got some good reviews."; } else if (percent <= 100.0F) { return "This film has got great reviews."; } return ""; } //Narrow multiple Search Results From Emby private BaseItem NarrowResults(string searchName, string[] type) { var result = LibraryManager.GetItemIds(new InternalItemsQuery { Name = searchName, IncludeItemTypes = type, }); if (!result.Any()) { var queryResult = LibraryManager.QueryItems(new InternalItemsQuery() { IncludeItemTypes = type, NameStartsWith = ReturnStartWithString(searchName) }); return queryResult.Items.FirstOrDefault(r => RemoveSpecialCharacters(r.Name).Contains(RemoveSpecialCharacters(searchName))); } if (!result.Any()) { var queryResult = LibraryManager.QueryItems(new InternalItemsQuery() { IncludeItemTypes = type, SearchTerm = ReturnStartWithString(searchName) }); return queryResult.Items.FirstOrDefault(r => RemoveSpecialCharacters(r.Name).Contains(RemoveSpecialCharacters(searchName))); } return LibraryManager.GetItemById(result.FirstOrDefault()); } private static string ReturnStartWithString(string name) { try { name = name[0].ToString(); } catch { } return name; } private static string RemoveSpecialCharacters(string sample) { var result = sample.Replace("-", string.Empty) .Replace("&", string.Empty) .Replace(":", string.Empty) .Replace(Regex.Match(sample, "/(([0-9][0-9][0-9][0-9])/)").Groups[0].ToString(), string.Empty) .Replace("1", "one"); return result.Replace(" ", string.Empty).ToLower(); } } } Now use the home brew Alexa Options class to give her random response from a dictionary: using System.Collections.Generic; namespace AlexaController.Alexa { class AlexaOptions { public static Dictionary<int, string> humanSpeechLibrarySpoiler = new Dictionary<int, string> { { 1, AlexaExpressiveInterjection("Spoiler Alert. ") }, { 2, AlexaOptions.AlexaExpressiveInterjection("Watch out.") + AlexaOptions.AlexaInsertStrengthBreak(StrengthBreaks.weak) + AlexaOptions.AlexaExpressiveInterjection("Spoilers!!") }, { 3, "Hope this doesn't spoil it for you. " + AlexaInsertStrengthBreak(StrengthBreaks.weak) }, { 4, "I don't want to spoil it for you. " + AlexaInsertStrengthBreak(StrengthBreaks.weak) }, { 5, AlexaSayWithEffect(Effect.whispered, "I don't want to spoil it for you.") + AlexaInsertStrengthBreak(StrengthBreaks.weak) + " But, here is the overview." + AlexaInsertStrengthBreak(StrengthBreaks.weak) } }; // ReSharper disable once ComplexConditionExpression public static Dictionary<int, string> humanSpeechLibraryAgree = new Dictionary<int, string> { { 1, AlexaEmphasis(" alright ", Emphasis.reduced) }, { 2, AlexaEmphasis(" Very well ", Emphasis.reduced) }, { 3, AlexaEmphasis(" sounds good ", Emphasis.reduced) }, { 4, AlexaExpressiveInterjection(" sure ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) }, { 5, AlexaExpressiveInterjection(" yeah ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) }, { 6, AlexaExpressiveInterjection(" OK ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) }, { 7, AlexaExpressiveInterjection(" you bet ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) } }; public static string HumanizeAlexaSpoiler() { int rInt = Plugin.r.Next(1, 5); return humanSpeechLibrarySpoiler[rInt]; } private static int tempHumanSpeechChoices = 1; public static string HumanizeAlexa() { int rInt = Plugin.r.Next(1, 7); while (tempHumanSpeechChoices == rInt) { rInt = Plugin.r.Next(1, 7); } tempHumanSpeechChoices = rInt; return humanSpeechLibraryAgree[rInt]; } public enum StrengthBreaks { weak = 0, medium = 1, strong = 2 } public enum Emphasis { /// <summary> /// Decrease the volume and speed up the speaking rate. The speech is softer and faster. /// </summary> reduced = 0, /// <summary> /// Increase the volume and slow down the speaking rate so the speech is louder and slower. /// </summary> strong = 1, /// <summary> /// Increase the volume and slow down the speaking rate, but not as much as when set to strong. This is used as a default if level is not provided. /// </summary> moderate = 2 } public enum Rate { slow = 0, medium = 1, fast = 2 } public enum Effect { whispered = 0 } public static string AlexaSayWithEffect(Effect effect, string text) { return "<amazon:effect name='" + effect + "'>" + text + "</amazon:effect>"; } public static string AlexaSayAsCardinal(string text) { return "<say-as interpret-as='cardinal'>" + text + "</say-as>"; } public static string AlexaSpellOut(string text) { return "<say-as interpret-as='spell-out'>" + text + "</say-as>."; } public static string AlexaInsertTimedBreak(string intDurationSeconds) { return "<break time='" + intDurationSeconds + "s'/>"; } public static string AlexaInsertStrengthBreak(StrengthBreaks strength) { return "<break strength='" + strength + "'/>"; } public static string AlexaEmphasis(string text, Emphasis emphasis) { return "<emphasis level='" + emphasis + "'>" + text + "</emphasis>"; } public static string AlexaSpeechRate(Rate rate, string text) { return ("<prosody rate='" + rate + "'>" + rate + "</prosody>"); } public static string AlexaExpressiveInterjection(string text) { return "<say-as interpret-as='interjection'>" + text + "</say-as>"; } } } Now she reply's in a very human and personal way. It's super cool guys! 2 Link to comment Share on other sites More sharing options...
chef 3745 Posted April 10, 2020 Author Share Posted April 10, 2020 OMG! 3 Link to comment Share on other sites More sharing options...
Swynol 375 Posted April 26, 2020 Share Posted April 26, 2020 very cool Link to comment Share on other sites More sharing options...
CarlosLima 148 Posted April 26, 2020 Share Posted April 26, 2020 Very very cool. Link to comment Share on other sites More sharing options...
BillOatman 500 Posted May 22, 2020 Share Posted May 22, 2020 But, not allowing your son to watch Deadpool is child abuse! Deadpool 2 not so much 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now