We have a iOS native app client making calls to a Bluemix speech2text service using Websockets in Direct interaction mode, which works great for us (very fast, very low latency). But we do need to retain a copy of the audio stream. Most audio clips are short (< 60 seconds). Is there an easy way to do that?
We can certainly have the client buffer the audio clip and upload it somewhere when convenient. This may increase memory footprint, particularly for longer clips. And impact app performance, if not done carefully.
Alternatively, we could switch to using HTTP interface and relay via a proxy, which could then keep a copy for us. The concern here (other that re-writing an app that works perfectly fine for us) is that this may increase latency due to extra hops in the main call thread.
Any insights would be appreciated.
-rg
After some additional research we settled on using Amazon S3 TransferUtility Mobile SDK for iOS. It encapsulates data chunking and multi-threading within a single object, and even completes transfer in the background after iOS suspends the app.
http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transferutility.html
The main advantages we see:
no impact on existing code--simply add a call to initiate a transfer
no need to implement and maintain a proxy server, which reduces complexity
Bluemix provides cloud object storage similar to S3 but we were unable to find an iOS SDK that supports anything other than a synchronous, single-threaded solution right out of the box (we were initially psyched to see 'Swift' support, but that has proven to be just a coincidental use of terms).
My two cents....
I would switch to the HTTP interface, if you make things tougher for your users, then they won't use your app and will figure out a better way to do things. You shouldn't have to rewrite the app - just the communications, and then have some sort of server side application that will "cache" those audio streams.
Another approach would be to leave your application as is, and just add a step to send the audio file to some repository, AFTER sending it to speech to text, in a different thread. In this case you could save off not only the audio file, but the text translation as well.
Related
I am trying to create an on-demand audio streaming platform (similar to Spotify) from scratch. It will have 1000 users (I am optimizing for time to build, not scalability as of right now).
I want to use web-based technologies ( I am experienced with React/Redux/Node). Could I get some advice on the architecture (what technologies I should use for the project)?
Here are things I need help with
What Storage service I should use for my music files (my song catalog is about 50000)
How to stream music from the storage service to each user
What server protocol I should use (RTMP/WebRTC/RTS)
(Optional) How to store data in cache to reduce buffer
I know this is a huge ask so thank you guys for your help in advance
What Storage service I should use for my music files (my song catalog is about 50000)
S3 (or equivalent).
Audio files fit this use case precisely, and you're already using AWS. If you find the cost too high, there are compatible services that are more affordable, all the way down to DIY on Minio.
How to stream music from the storage service to each user
Use a CDN (or multiple CDNs) to optimize delivery and keep the latency low. CDNs are also better at spoon-feeding slow clients.
What server protocol I should use (RTMP/WebRTC/RTS)
Normal HTTP! That's all you need, and that's all that's been necessary for decades for this use case.
RTMP is a dead protocol, only supported by Flash on the client side. Its usage today is limited to sending source streams from video encoders, and even that is well on its way out the door.
WebRTC is intended for low latency connections, like voice calls and video chat. This is not something that matters in a unidirectional stream. You actually want a robust streaming mechanism... not one that drops audio like a cell phone to keep up to realtime.
RTSP is not something you can use in a browser, and is overly complex for what you need.
Just a simple HTTP service is sufficient. Your servers should support ranged requests so that the browser can lose a connection and still pick up right where they left off, without the listener even knowing. (All CDNs support this, as does any properly configured web server.)
(Optional) How to store data in cache to reduce buffer
CDNs will generally improve performance of the initial connect and load. I also recommend pre-loading the next track to be played in the list so that you can start it immediately. In most browsers, you can actually start the next track at the tail end of the previous track for a smooth transition.
I have been working on a Web App for visualizing live data. It is crucial that this data is kept up to date on the client side without such updates being invoked directly by the client (e.g. no button presses or refreshing the page). Currently, on page load, I grab the current data set from a database (DynamoDB) via Ajax, and subsequent updates are pushed to any listening clients every 5 minutes via a Websockets connection (using Socket.io).
I have overlooked the computational load of this update job. It has to mine some data, process it, update the database, and send the update out to all clients. As a result, the web server is left unresponsive for about 30 seconds with each update. Furthermore, my current architecture limits me from putting my server behind a load balancer, which is something I anticipate coming up in the future. For both these reasons, I really need to get this update job off my web server.
I am relatively inexperienced in web development, and I don't feel I am knowledgeable enough about these technologies to know the drawbacks of the solutions I have come up with. Currently, I am considering:
Break the update off into a separate process so it does not block the Node event loop. This would solve my issue in the short term, but if I ever want to load balance my application, I can't have the update running on multiple machines.
Drop Websockets entirely and just have the client query the database every 5 minutes, while a separate process (or separate server if I want load balancing) keeps the database up to date without interacting directly with the client. Will this kind of access pattern put too much load on my db?
Have a separate server run the update, and send the result via Websockets (or maybe some other protocol) to my load balanced application servers, which then push that update to all listening clients as usual. Is this even possible?
Perhaps there are other solutions. It seems like this would be a relatively common problem, so I was hoping I could find some guidance here. What are the potential issues with the solutions I have proposed, and are there other possible solutions that my suit my use case better?
It sounds like you want one process sitting somewhere which crunches the data and publishes it to a stream. Clients can then subscribe to the stream as and when they like. Redis handles streams nicely, you could process your data and push it into a redis stream. You could then create a small node service which subscribes to the redis stream and pushes the formatted data out over a websocket or via polling.
In this scenario you can then scale up either the publishing process (the one crunching the numbers) if your data load goes up, or scale up your subscribed process (which serves the data over a websocket to browsers) if you get an influx of clients watching the data.
You can also easily distribute the hosting of these services across other machines, and even write them in different languages if you decide the number crunching needs something like threading.
You're then left with the issue of clients (web browsers) consuming this data with a load balance in-between. This can be a hard problem if you use websockets and is bundled with pros and cons. But importantly you'll have separated your data crunching from your result publishing and that'll isolate out your issue to only the load balancing.
I have done pretty much the same to check ressources on some of our servers.
I have a C# service getting the information on each server that we manage, sending them to a queue (Amq).
From there, I have a stomp client fetching data from amq and emiting them to a websocket.
My main micro service is fetching the data to save them into a db.
My visualisation webapp is connected to the same ws and is fetching the data as they are sent to display them.
The Amq step isn't mandatory at all, it's just something I had to work with (historical).
I don't know what type of data your are working with, so I don't know if my solution can apply to you.
Don't hesitate if I'm not clear or you have any question.
This is a big question and I'm not going to try and give you a definitive answer.
For option 2
It really depends on how expensive your queries are. You can make DynamoDB fast if you pay for enough throughput. That said, on the face it, re-loading your whole dataset, when that sounds like its probably large, probably isn't good engineering.
For option 3
This option seems best to me if its achievable, although admittedly its hard to say with such a complex system - obviously you can't share your whole project.
Given your are already using AWS you might want to look into AWS Lambda. If you can move the update process into a stand alone job, you can host it on lambda and move the load off the web server. Lambda is essentially infinitely scalable and you only pay for the compute you use.
This really depends on you being able to split the update task off into a separate service. Its likely you would need a fair bit of refactoring to isolate it as a service. If you can break little bits off at a time, and make the move gradually, even better.
If you consider trying this, and you've not used Lambda before, I would definitely start small with some hello world examples. Then try a very simple service in your application, and build up to taking on the update service.
You might also consider looking in AWS Simple Message Queue Service to handle the comms between clients and server.
Database tuning
If a lot of your update time is spent waiting for database actions to complete, rather than server processing, you can consider tuning that side of things up. Things to consider are:
Buying more throughput
Using batch operations (as these move load to DynamoDB from your server)
Tuning keys, indexes and database access
I'm a Rails developer who has just migrated to Node and I've decided to write an angular application backed by an postgres/express.js REST api. I use the api primarily for CRUD operations thus far, but I want to start a realtime game instance when two players visit a certain page(challenge each other). I'm thinking of using socket.io to accomplish the realtime functionality.
The game is similar to that of pokemon on gameboy, in which to players take turn performing certain actions until one of them wins.
I have the following questions:
Should I have a separate server to handle the game using socket.io, or can i use the same as the one my API operates on?
Should I use a service like Pusher or can I create the architecture myself?
How would I go about making sure no data is lost, if say, a player disconnects during a game?
At which point (number of concurrent connections/request per second) would I run into performance issues? 100, 1000, 10000?
Thanks
If the realtime logic is closely related to the CRUD stuff (i.e. realtime events are a direct result of writes to the API), and you expect somewhat equal usage of both aspects of the system, then I'd put both on the same server.
I highly recommend using a realtime push service if possible (disclaimer: I work for Fanout.io). It'll be simpler and probably less expensive too.
The key to making sure data is not lost is to persist it on the server before sending. Don't depend on the realtime layer for persistence (biggest mistake you can make). When the client reconnects, it can request data it may have missed via the normal API. So, just get your CRUD stuff correct and then layer realtime eventing on top. You can create a very network resilient service this way.
You should be able to get to a few hundred concurrent connections without much thought. Going beyond will take architecture planning. Of course, if you delegate to a push service then you don't have to worry about this, at least for the realtime part.
We have an embedded box. The specs of the CPU is medium speed (600MHz) and RAM is between 512MB to 2GB depending on configuration. The system consists of data layer to process incoming data from hardware and needing to be displayed both remotely and on an HDMI output.
Seeing the remote aspect is as important as the local display, we have architected a client-server solution. For the server, it just needs to respond to requests for data. The data needs to come from the internals of another process (IPC interaction) and return it formatted for the client.
For the server we are thinking of using node.js. The data is spec'ed to be formatted into json messages, so using JavaScript and json is simple.
However, are there any better/other server options to consider?
The main requirement is the server can be extended to interact with the data process and be able to process and respond to requests.
We could write it ourselves, but feel that there must be usable tech to leverage already.
Thanks.
I am assuming that you need output as a webpage only.
It depends.
If your team knows java/servlet well, you can do using simple jetty/servlet/jsp combination.
But if you have team good with javascript/node.js, go with it. Although, I am not sure about stability requirements you have, because node.js is quite stable but it haven't reached 1.0 yet.
Is there an easy way to manage offline data with a web app, and synchronize with a server when there is a connection? I have been looking at Meteor, CouchDB and the likes, but still not sure what would be the least painfull way.
I could of course implement it myself with sockets or something similar, but if something is already made for the purpose, I don't see a reason to do it again.
I'm planning to work with Node as the server.
Thanks
You're talking about two things; 1) How to store/persist data if/when offline (storage mechanism), and 2) How to synchronize with a server when online (communication mechanism). The answer to 1 is some kind of local storage, and there any several ways of doing that (localstorage, websql, filesystem APIs etc) depending on your platform. The answer to 2 really depend on how urgent your synchronization needs are, but in general you can use HTTP itself with periodic (long-) polling, websockets and similar.
On top of both storage and communication mechanisms there are numerous libraries that make the job simpler, like Meteor (communication) and CouchDB (storage), but also many many more. There are even libraries that take care of the actual synchronization mechanism (with possible conflict resolution as well), but this very much depends on your actual application.
Updated: This framework looks promising, but I haven't tested it myself:
http://blog.nateps.com/announcing-racer-experimental-realtime-model
You might want to look at cloud services as well. These are best if you are developing a new application as they push you more to a serverless model, and of course you have to be happy using a service.
Simperium (simperium) is an interesting cloud service - the only one I can find today that does syncing (unlike Firebase and Spire.io who are similar in other respects), and for iOS it includes offline storage, while for JavaScript clients you'd need to cover the local storage yourself using HTML5 features. Backbone.js seems to have some support for this, and Simperium can integrate with Backbone, using a similar API style.
For non-cloud services, Derbyjs (derbyjs) is an open source project that includes Racer, a data synchronization library (mentioned by the earlier answer) - both are under rapid development and not yet complete, but look interesting if your timescales allow, and don't require a cloud service. There is a comparison of Derbyjs to Meteor that is useful - although it's written by the Derbyjs developers it's not too biased.
I also looked at CouchDB, which has some interesting built-in replication features, but I didn't like its use of indexes that are updated lazily when a query needs them (or by a batch process), and I wasn't happy with exposing the server DB directly to clients to enable replication/sync. Generally I think it's best to decouple the client side local storage from the server side DB, and of course for a web app it would be hard to use CouchDB on the client.