alxhotel / chromecast-api Goto Github PK
View Code? Open in Web Editor NEW:tv: Chromecast Node.js module
License: MIT License
:tv: Chromecast Node.js module
License: MIT License
Hi, this looks like a great library, but I have trouble installing it with Vue.
I have run npm install chromecast-api
and after this, ran the following code from the tutorial:
const ChromecastAPI = require('chromecast-api')
const client = new ChromecastAPI()
client.on('device', function (device) {
var mediaURL = 'http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4';
device.play(mediaURL, function (err) {
if (!err) console.log('Playing in your chromecast')
})
})
When opening the app, I get the following error in the Chrome developer console:
It looks like it already occurs when importing the library, as something as short as new ChromecastAPI()
also gives the error. This is most likely an installation issue or a incompatibility with another installed NPM package in my part.
Is this a known issue? Thanks.
Note: #34 looks similar
I was trying to play a few youtube videos on loop, but noticed the finished event does not fire for youtube videos. It looks like status.playerState is set to BUFFERING instead of IDLE when the video is finished. Here is an example of a finished youtube status event that I am getting:
{
mediaSessionId: 1348606427,
playbackRate: 1,
volume: { level: 1, muted: false },
playerState: 'BUFFERING',
customData: { playerState: 0 },
idleReason: 'FINISHED'
}
I was able to setup the API, but status reporting does not seem to work for me.
Is it possible google changed something in the background or it never worked like this?
const ChromecastAPI = require('chromecast-api')
const client = new ChromecastAPI()
client.on('device', (device) => {
console.log(device.friendlyName, 'connected')
device.getStatus((status) => {
console.log(device.friendlyName, status)
})
// ==== Throws error: ====
// Bedroom speaker Error: no session started
// at C:\Users\hgghy\Documents\Codes\castApi\node_modules\chromecast-api\lib\device.js:77:18
// at C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2-client\lib\controllers\receiver.js:86:5
// at C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2-client\lib\controllers\receiver.js:31:5
// at fn.onmessage (C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2-client\lib\controllers\request-response.js:27:7)
// at fn.emit (node:events:402:35)
// at Channel.onmessage (C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2-client\lib\controllers\controller.js:16:10)
// at Channel.emit (node:events:390:28)
// at Client.onmessage (C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2\lib\channel.js:23:10)
// at Client.emit (node:events:402:35)
// at PacketStreamWrapper.onpacket (C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2\lib\client.js:81:10)
// at PacketStreamWrapper.emit (node:events:390:28)
// at TLSSocket.<anonymous> (C:\Users\hgghy\Documents\Codes\castApi\node_modules\castv2\lib\packet-stream-wrapper.j at TLSSocket.emit (node:events:390:28)
// at emitReadable_ (node:internal/streams/readable:601:12)
// at processTicksAndRejections (node:internal/process/task_queues:82:21)
// ==== Does nothing: ====
device.on('status', (status) => {
console.log(device.friendlyName, status)
})
})
After following the basic example I can not get any kind of interaction to work with my chromecast from this api. I can verify that device is defined as when it is returned in callback from client.on('device', callback). I confirm that device.friendlyName is the name of the chromecast I expected.
I can not get any of prototype/class device function/methods to be recognized. Same issue with client.setVolume().
Here is returned error from VS Code
Exception has occurred: TypeError TypeError: Cannot read property 'setVolume' of null at Device.setVolume (e:\dev\test\node-chromecast\node_modules\chromecast-api\lib\device.js:229:17) at Client.<anonymous> (e:\dev\test\node-chromecast\src\index.js:15:12) at Client.emit (events.js:223:5) at Client._updateDevice (e:\dev\test\node-chromecast\node_modules\chromecast-api\lib\client.js:40:10) at onEachAnswer (e:\dev\test\node-chromecast\node_modules\chromecast-api\lib\client.js:66:46) at Array.forEach (<anonymous>) at EventEmitter.<anonymous> (e:\dev\test\node-chromecast\node_modules\chromecast-api\lib\client.js:95:28) at EventEmitter.emit (events.js:223:5) at Socket.<anonymous> (e:\dev\test\node-chromecast\node_modules\multicast-dns\index.js:49:43) at Socket.emit (events.js:223:5) at UDP.onMessage [as onmessage] (dgram.js:874:8)
I am using 3rd gen Chromecast.
process.versions.node = "12.14.1"
Let me know of any other information you may need to help fix this issue. Is there any other kind of setup i'm missing? Does the device have to be in debug mode? I mean, the device is recognised by this api, I just cant interact with it besides detection.
Edit: Back to this example:
const ChromecastAPI = require('chromecast-api')
const client = new ChromecastAPI()
client.on('device', function (device) {
var mediaURL = 'http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4';
device.play(mediaURL, function (err) {
if (!err) console.log('Playing in your chromecast')
})
})
No errors but nothing happens. The chromecast is at the idle screen too.
If Chromecast isn't playing a supported app (eg in its do-nothing mode) the first getStatus() returns the expected error. A repeat call throws 'Cannot read property 'getStatus' of undefined' because device.client is not null.
Proposed code change:
// device.js
getStatus (callback) {
this._tryJoin((err) => {
if (err) {
this.client = null // add this line
return callback(err)
}
this.player.getStatus(callback)
})
}
Hey all,
I was wondering if you would be interested if I rewrite the code a bit, so that everything is in classes. If you are interested, I can make a pull request with my current changes.
If you're interested in the soft rewrite, I would welcome feedback very much.
I have a barebones script based off of the example code in the README, a simple listener on the client that listens for the device event, and a console.log that prints out the resulting device objects.
After a few moments, i receive an Unhandled Error event showing a timeout while waiting for a response from 192.168.1.2.
After checking my NetGear Nighthawk router's connected devices screen, it shows that there is no device on that IP address. There is also no events available for me to listen for and handle this event, and the app simply crashes.
events.js:353
throw er; // Unhandled 'error' event
^
Error: connect ETIMEDOUT 192.168.1.2:8060
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146:16)
Emitted 'error' event on ClientRequest instance at:
at Socket.socketErrorListener (_http_client.js:475:9)
at Socket.emit (events.js:376:20)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
errno: -4039,
code: 'ETIMEDOUT',
syscall: 'connect',
address: '192.168.1.2',
port: 8060
}
here is the code for my script. Like I said, super simple...
const ChromecastAPI = require('chromecast-api')
const Client = new ChromecastAPI()
Client.on('device',(device)=>{
console.log('device ', device)
})
Before the error is emitted and the app crashes, it does fine all of the Chromecasts, Nest Hubs and Cast Groups on my network. The app just doesnt run long enough for me to really do anything
Hie @alxhotel ,
I am really impressed by your quick response and update to the API for youtube video integration.
While, I can see we can add subtitles while playing normal media ( mp4 ). I am curious, like is it possible to do the same with youtube video streaming?
I am trying to play youtube videos using this package, and add subtitles to the video. I have created subtitles and upload on github which can be fetched by raw content. like : https://raw.githubusercontent.com/google/WebFundamentals/master/src/content/en/fundamentals/design-and-ux/responsive/_code/chrome-subtitles-en.vtt
So, I want to know how can i use this srt file to display subtitle while youtube video steaming.
Thanks.
🚨 You need to enable Continuous Integration on all branches of this repository. 🚨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.
Since we didn’t receive a CI status on the greenkeeper/initial
branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.
If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/
.
Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial
branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.
TypeError: Cannot read property 'getStatus' of undefined
at [...]/chromecast-api/lib/device.js:179:19
at Device._tryJoin ([...]/chromecast-api/lib/device.js:146:29)
at Device.getStatus ([...]/chromecast-api/lib/device.js:174:10)
device.js.getStatus starts with calling this._tryJoin. tryJoin adds to the device the client and the player object. but if the device has a client and no player, it skips this. this means there is no player and this.player.getStatus fails.
The issue can be fixed by changing the guard close of _tryJoin from "if (this.client)" to "if (this.client && this.player)".
Have a nice day !
Check if we can still connect to the Chromecast with a VPN connection enabled.
Hi,
when listening for chrome cast devices single chrome cast devices and pre defined groups of chromecast devices can be retrieved treated as further chromecast devices with a unique name/adress. While trying to play media on that group only one chromecast device is actually playing the media. Any idea how all chromecast devices of the group will retrieve the command to play the media (without telling each single device to play the media)?
I can't get YouTube to work, this is the error I'm getting:
self.playlistId = PLAYLIST_ID_REGEX.exec(body)[1]
TypeError: Cannot read property '1' of null
Seems to be coming from youtube-remote
Code I'm using:
const ChromecastAPI = require('chromecast-api');
const client = new ChromecastAPI();
client.on('device', function (device) {
console.log(device);
if (device.name !== "Google-Nest-Mini-[ID]._googlecast._tcp.local") return;
const mediaURL = 'https://youtube.com/watch?v=[ID]';
device.play(mediaURL, function (err) {
if (!err) console.log('Playing in your chromecast');
});
});
Hi!
Is there a way to get the current playing item and its time?
Just showing appreciation for your work on Chromecast and Node! This is awesome!
Hey. Just checked simple example from README and have weird issue: official Chromecast iOS app crashes all time while streaming from node with this.
Kinda weird, had no issues like that with castv2-client
.
I started getting this error when I updated node to v20.16.0 and also [email protected]
Using this code...
const ChromecastAPI = require('chromecast-api')
chromecastClient = new ChromecastAPI();
Results in:
TypeError: ChromecastAPI is not a constructor
at castBrowse (/var/www/html/node/indexer.js:1849:28)
at WebSocket. (/var/www/html/node/indexer.js:2247:17)
at WebSocket.emit (node:events:519:28)
at Receiver.receiverOnMessage (/var/www/html/node/node_modules/ws/lib/websocket.js:1070:20)
at Receiver.emit (node:events:519:28)
Is there a work around or fix for this?
At the moment it's not possible to play YouTube Music Links on a Smart Speaker (e.g. a Nest Audio).
It IS possible to play YouTube Music Songs through the YouTube Music App, so that shouldn't be a problem I hope? Also it is possible to play general Audio Files on Smart Speakers.
Will the library emit an event when the video has ended?
If not, it would be a nice feature to be able to start the next video when the current one finishes.
I was running the original usage code from README.md, but it didn't work. So I modified it a bit to be sure I'm getting devices:
const ChromecastAPI = require('chromecast-api');
const client = new ChromecastAPI();
console.log(client.devices);
client.update();
console.log(client.devices);
client.on('device', (devices) => console.log(devices) );
console.log(client.devices);
But nothing seemed to work.
The output was:
[]
[]
[]
I can't get it to find devices, even though I have my devices all turned on, with chromecast working. And I know it works, because when I use Popcorn Time it finds the devices with chromecast. What am I doing wrong?
Hi,
I had an issue on my side using status events, it seems there is no IDLE playerState at all, I debugged the code and add a temporary fix in the file lib/device.js at line 46 :
// TODO: might be useful for callback?
this.client.on('error', (err) => {
debug('Error: %s', err.message)
this.client.close()
})
this.client.on('status', status => {
if ( !status.applications )
this.emit('status', { playerState: 'IDLE' });
});
debug('Connecting to device: ' + this.host)
If you have a better one I'm very interested.
Thanks in advance...
Currently there is no simple way to list all the devices discover so far.
Something like a getter
client.devices
This will really make the API simpler to use.
One more issue: subtitles simply don't show up. Checked both README example and other available subtitles via URL with another video.
Hey all,
Since music support is added, I was wondering if this library is a good place for a playlist feature. I'm imagining a class where media objects are stored and played in the order they are added, shuffled or whatever.
I'm not sure if you want to keep this library low-level, or if you are open to expand it with some features.
Is it possible to cast local mp3 files to a device? If not i would like to request this feature.
Nice work so far!
Looking at adding this to an app, which under our internal code quality rules requires strongly typed libs. Given I'll have to type it, wondering:
Willing to do a PR with whichever
Hello, I'm trying to cast with my own generated subtitles.
Here is an example of my media object where 192.168.0.2 is the local IP of my PC with an NodeJS express http server, the local video plays correctly but subtitles don't appear:
const media = {
url : 'http://192.168.0.2/video.mkv',
subtitles: [{
language: 'en-US',
name: 'English',
url: `http://192.168.0.2/subtitles.vtt`,
}],
subtitles_style: {
backgroundColor: '#FFFFFF00', // see http://dev.w3.org/csswg/css-color/#hex-notation
foregroundColor: '#FFFFFFFF', // see http://dev.w3.org/csswg/css-color/#hex-notation
edgeType: 'OUTLINE', // can be: "NONE", "OUTLINE", "DROP_SHADOW", "RAISED", "DEPRESSED"
edgeColor: '#000000FF', // see http://dev.w3.org/csswg/css-color/#hex-notation
fontScale: 1.2, // transforms into "font-size: " + (fontScale*100) +"%"
fontStyle: 'BOLD', // can be: "NORMAL", "BOLD", "BOLD_ITALIC", "ITALIC",
fontFamily: 'Droid Sans',
fontGenericFamily: 'SANS_SERIF', // can be: "SANS_SERIF", "MONOSPACED_SANS_SERIF", "SERIF", "MONOSPACED_SERIF", "CASUAL", "CURSIVE", "SMALL_CAPITALS"
}
}`
If I just replace 'http://192.168.0.2/subtitles.vtt' by your example 'https://raw.githubusercontent.com/alxhotel/chromecast-api/master/test/captions_styled.vtt' it works. Even if my subtitles.vtt contains exactly the same text as captions_styled.vtt
The fact that the video is playing proves that my chromecast is able to reach my local express server.
Is that a limitation of Chromecast? Subtitles must be hosted on a HTTPS website maybe?
I tried it because i thought it would work, but is it possible to play local video files? I couldn't get it to work. If so, how?
Thanks in advance!
Is there a way to turn off the tv once the content has stopped playing?
And, is there a way to introduce a delay after connecting but before playing the content? This is because on my TV I noticed that my speaker takes a few seconds to turn on and connect, and so the media starts playing but there's no sound. Introducing a delay of 5-10 seconds would fix this.
Thank you, this is a great library overall and I appreciate your work!
Hello. I've been developing an app for casting local videos from PCs via Chromecast, and I am using your package for the backend. Now I've added the capacity to load subtitles. However, during my tests, I noticed that .srt files do not work, only vtt ones. Given that most people use .srt, this could end up being a bit of a hassle for the user (who probably will have to convert the file first).
So, my question is, are .srt files really not supported or am I doing something wrong?
Thank you very much for your hard work,
Cheers
When I import the chromecast-api into my react-app, I get this message: Uncaught Error: illegal token '<' (/cast_channel.proto, line 1)
Can you help me the solve it?
Also when I implement the rest of your code I got another error:
TypeError: dgram.createSocket is not a function
push../node_modules/multicast-dns/index.js.module.exports
node_modules/multicast-dns/index.js:25
I would appreciatie it if you could help me :)
Hi!
Is It possible to use custom styled receivers?
Hi! It would be nice if it was possible to control a running session that was started with a different application, for instance Plex. Then it would be possible to pause/resume through this package.
I tried pause/resume but I get the following error:
/home/user/develop/tests/api/node_modules/chromecast-api/lib/device.js:221
this.player.play(callback)
^
TypeError: Cannot read property 'play' of undefined
Presumably because the video wasn't started using this package.
Thanks!
Where i can subscript to volume change of the device?
Hi folks,
I was wondering - how could I cast not a mediafile but my device's screen (video only) using this? If it's not supported just yet, how could one add this functionality?
I didn't find anything in the documentation about this topic, Is there any way to have the current time of the media launched ? For instance, if I add subtitles while watching a video, I don't want to restart the video from the beginning but where I was. If it doesn't exist, it could be a great feature !
I was thinking if I can also use this library to send images to the chromecast. And can you also send sound only over HDMI (by pointing the URL to an mp3)?
It seems logical, but I didn't find it in the documentation.
I'm currently thinking of buying a chromecast and if it supports casting images, that would make the choice easier.
Hi!
Is there a chance that this package will support chromecast audio (the device) in the future?
This is the best chromecast package I've ever used, but this functionality would be highly useful.
Best Regards.
EDIT: I don't know exactly why, but it started detecting ChromeCast Audio correctly. I'm closing the issue, sorry for trouble.
Hello, I'm trying to run the code bellow, but devices are never found even tho I have a lot of them here.
const ChromecastAPI = require('chromecast-api')
const client = new ChromecastAPI()
client.on('device', function (device) {
console.log(device)
})
I can see the devices using the cast
option in Google Chrome.
Could this be a firewall problem? I'm using Ubuntu WSL on Windows 11. (Also tested with a XUBUNTU machine and didn't worked)
Edit: sorry, should have thought about this more before opening an issue. is there any way to pass a mediastream object to cast on the chromecast?
This way we can get user screens or video input and cast that
Hi, I'm wondering if this has HLS support? I have a master.m3u8 file that gives different m3u8 url:s for different quality stream (example 720p, 1080p). Will this package support that, or should I give the quality stream directly (skip the master.m3u8 step)?
I was thinking it would be interesting to have a feature to be able to show HTTP pages (by URL) on the Chromecast.
https://github.com/DeMille/url-cast-receiver
So instead of specifying a media item, you specify a webpage. I believe we'd need a "Custom Media Receiver" like above.
Unsure if this custom receiver should be integrated in this project or if we'd want to be able to let the user of the library specify a path/URL to the custom media receiver.
I have run your examaple, and it loops over and creates "device" for each chromcast, is there a way to select a specific one or get it to stop when it matches player X?
As I want to play on only specific clients and not for it to play on every client in my house, thanks.
Thanks for your work.
Hi
How can i cast m3u8 files?
thanks
Hello,
I've an ip cam but it deos not offer a direct access to the stream. I want to stream it on my cromecast.
After research i found that it is possible to get the stream via rtsp using ffmpeg.
Now i'm able to get an hsl(?) video using the following command
ffmpeg -i rtsp://admin:[email protected]/h264_stream -fflags flush_packets -max_delay 5 -flags -global_header -hls_time 5 -hls_list_size 3 -vcodec copy -y ./static/ipcam/index.m3u8
I prepared a function on my server code to serve the file
@Get('/hslVideo')
hslVideo(@Response() res, @Request() req) {
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Max-Age': 2592000, // 30 days
/** add other headers as per requirement */
};
if (req.method === 'OPTIONS') {
req.writeHead(204, headers);
req.end();
return;
}
const filePath = path.resolve('static/ipcam/index.m3u8');
console.log('filePath:', filePath)
readFile(filePath, function (error, content) {
res.writeHead(200, { 'Access-Control-Allow-Origin': '*' });
if (error) {
if (error.code == 'ENOENT') {
readFile('./404.html', function (error, content) {
res.end(content, 'utf-8');
});
}
else {
res.writeHead(500);
res.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
res.end();
}
}
else {
res.end(content, 'utf-8');
}
});
}
Thus i start ffmpeg command and start it on chromecast
device.play(
{
url: `http://${ipaddr}:3000/chromecast/hslVideo`,
contentType: "video/H264"
},
function (err) {
if (err) {
console.log(err);
}
},
);
But i end up in an error that I really do not understand.
Am I missing something?? I red that with this kind of file i should me able to play on the chromecast.
I noticed that currently we can control only the Youtube app.
In my opinion there is no reason not to enable the media controls (play, pause, volume, seek ...) for any other apps playing medias.
I edited your code to fallback to DefaultMediaReceiver
for unknown apps, and indeed I was able to play, pause, change volume etc for Spotify, Amazon Prime Video and Netflix.
I simply edited this part
const filtered = sessions.filter((session) => {
return (app)
? session.appId === app.APP_ID
: SUPPORTED_APP_IDS.includes(session.appId)
})
const session = filtered.shift();
if (session) {
app = app || SUPPORTED_APPS[session.appId];
this.client.join(session, app, callback)
} else if (app) {
this.client.launch(app, callback)
} else {
callback(new Error('no session started'))
}
to:
const session = sessions.shift();
if (session) {
app = app || SUPPORTED_APPS[session.appId] || DefaultMediaReceiver;
this.client.join(session, app, callback)
} else if (app) {
this.client.launch(app, callback)
} else {
callback(new Error('no session started'))
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.