question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Refresh Image Without Blanking Screen

See original GitHub issue

I’m trying to cast a webpage that displays stats from a headless box to my Chromecast using Node.js. My current implementation involves using PhantomJS in an external process to render the webpage to an image and then cast that image to the Chromecast using node-castv2-client, and then repeat that in an interval. Here is my code as it stands:

/*
 * Written by Turing Eret
 * Based on code example by Thibaut Séguy from
 * https://github.com/thibauts/node-castv2-client/blob/master/README.md
 */

var Client = require('castv2-client').Client;
var DefaultMediaReceiver  = require('castv2-client').DefaultMediaReceiver;
var mdns = require('mdns');
var http = require('http');
var internalIp = require('internal-ip');
var router = require('router');
var path = require('path');
var fs = require('fs');
var mime = require('mime');
var finalhandler = require('finalhandler');

var port = 8800;

var prefixPath = startServer();

var browser = mdns.createBrowser(mdns.tcp('googlecast'));

browser.on('serviceUp', function(service) {
  console.log('found device "%s" at %s:%d', service.name, service.addresses[0], service.port);
  if(service.name == process.argv[2]) {
    onDeviceFound(service.addresses[0]);
  }
  browser.stop();
});

browser.start();

function onDeviceFound(host) {
  var client = new Client();

  var statsFile = 'stats.png';

  var statsImagePath = prefixPath + statsFile;

  client.connect(host, function() {
    console.log('connected, launching app ...');

    client.launch(DefaultMediaReceiver, function(err, player) {
      var media = {
        contentId: statsImagePath,
        contentType: 'image/png'
      };

      player.on('status', function(status) {
        console.log('status broadcast playerState=%s', status.playerState);
      });

      console.log('app "%s" launched, loading media %s ...', player.session.displayName, media.contentId);

      var loadStats = function() {
        // renderStats('stats.png'); //Will eventually reload and rerender the page.
        player.load(media, { autoplay: true }, function(err, status) {
          console.log('media loaded playerState=%s', status.playerState);
        });        
      }

      loadStats();   

      setInterval(function() {
        console.log('Executing interval function.');
        loadStats();
      }, 5000); //Set to 5 seconds for debug purposes.

    });
  });

  client.on('error', function(err) {
    console.log('Error: %s', err.message);
    client.close();
  });

}

function startServer() {
  var route = router();
  var ip = internalIp();
  var prefix = 'http://' + ip + ':' + port + '/';

  route.all('/:path', function(req, res) {
    serveFile(req, res, req.params.path, prefix);
  });

  http.createServer(function(req, res) {
    route(req, res, finalhandler(req, res))
  }).listen(port)
  console.log('Started simple webserver at %s', prefix);

  return prefix;
}

function serveFile(req, res, filePath, prefix) {
  console.log('Serving file: %s', filePath)
  var stat = fs.statSync(filePath);
  var total = stat.size;
  var range = req.headers.range;
  var type = mime.lookup(filePath);

  res.setHeader('Content-Type', type);
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Refresh', '5;url=' + prefix + filePath);

  if (!range) {
    res.setHeader('Content-Length', total);
    res.statusCode = 200;
    return fs.createReadStream(filePath).pipe(res);
  }

  var part = rangeParser(total, range)[0];
  var chunksize = (part.end - part.start) + 1;
  var file = fs.createReadStream(filePath, {start: part.start, end: part.end});

  res.setHeader('Content-Range', 'bytes ' + part.start + '-' + part.end + '/' + total);
  res.setHeader('Accept-Ranges', 'bytes');
  res.setHeader('Content-Length', chunksize);
  res.statusCode = 206;

  return file.pipe(res);
};

Now, this code has two issues. First off, whenever the interval hits, the Chromecast redisplays the image, but the screen blanks out before doing so. Ideally, it wouldn’t blank out like that. Second, when the Chromecast redraws the designated image, I can see that it is not being reloaded from the webserver, which means that even if the image changes, nothing will change on screen. How do I fix this? Thanks.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:19 (17 by maintainers)

github_iconTop GitHub Comments

1reaction
jrdagalacommented, Sep 23, 2015

Here is my complete code of the test application I’ve created. I already know my chromecast host, so I set it to connect it directly.

var Client                = require('castv2-client').Client;
var DefaultMediaReceiver  = require('castv2-client').DefaultMediaReceiver;
var util                  = require("util");

function playFile(media, player){
    player.load(media, { autoplay: true }, function(err, status) {
      console.log('media loaded playerState=%s', status.playerState);

    setTimeout(function() {
      console.log("STOPPING FILE")
      player.stop(function(err, status) {
          console.log("STOP ERROR: " + util.inspect(err))
          console.log("STOP STATUS: " + util.inspect(status))
      });
    }, 3000);
  });
}

function connectToDevice(host) {

  var client = new Client();

  client.connect(host, function() {
    console.log('connected, launching app ...');

    client.launch(DefaultMediaReceiver, function(err, player) {

      var mediaList = [
        {
          autoplay : true,
          preloadTime : 3,
          activeTrackIds : [],
          playbackDuration: 10,
          media: {
            contentId: "http://10.1.2.132:9500/example-slide-1.jpg",
            contentType: "image/jpeg",
            streamType: 'BUFFERED'
          }
        },
        {
          autoplay : true,
          preloadTime : 3,
          activeTrackIds : [],
          playbackDuration: 10,
          media: {
            contentId: "http://10.1.2.132:9500/example-slide-2.jpg",
            contentType: "image/jpeg",
            streamType: 'BUFFERED'
          }
        },
        {
          autoplay : true,
          preloadTime : 3,
          activeTrackIds : [],
          playbackDuration: 10,
          media: {
            contentId: "http://10.1.2.132:9500/example-slide-3.jpg",
            contentType: "image/jpeg",
            streamType: 'BUFFERED'
          }
        }
      ];

      console.log('app "%s" launched, loading medias...', player.session.displayName);

      player.on('status', function(status) {
        console.log('status broadcast = %s', util.inspect(status));
      });

      // loads multiple items
      // player.loadQueue(mediaList, {repeatMode: "REPEAT_ALL"}, function(err, status) {
      //   console.log("Load QUEUE: " + util.inspect(status));
      // })

      // Playing Single images every 10 seconds
      var i = 0;
      playFile(mediaList[i].media, player)
      setInterval(function() {
        i++;
        if(i == mediaList.length)
          i = 0;

        playFile(mediaList[i].media, player)
      }, 10000)

    });

  });

  client.on('error', function(err) {
    console.log('Error: %s', err.message);
    client.close();
  });

}

connectToDevice("10.1.2.69");

Code for loadQueue on Media Controller

MediaController.prototype.loadQueue = function(mediaList, options, callback) {
  var self = this;

  if(typeof options === 'function' || typeof options === 'undefined') {
    callback = options;
    options = {};
  }

  var data = { type: 'QUEUE_LOAD' };
  data.items = mediaList;
  data.repeatMode = (typeof options.repeatMode !== 'undefined') ? options.repeatMode : "REPEAT_OFF";

  self.request(data, function(err, response) {
    if(err) return callback(err);
    if(response.type === 'LOAD_FAILED') {
      return callback(new Error('Load failed'));
    }
    var status = response.status[0];
    callback(null, status);
  });

}

Code for Default-Media-Receiver for loadQueue

DefaultMediaReceiver.prototype.loadQueue = function(media, options, callback) {
  this.media.loadQueue.apply(this.media, arguments);
};
0reactions
thibautscommented, Dec 10, 2016

Closing for inactivity.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reload image without refreshing the page - javascript
See this: Updating a picture without page reload document.getElementById('yourimage').src = "url/of/image.jpg?random="+new Date().getTime();.
Read more >
How can I refresh image displayed by fbi without black screen ...
Everything works fine for one image, if I don't refresh it. But when I need to refresh it, there is ~2 seconds of...
Read more >
Black screen this mess. Image Loading Failure. Reload Image
Let us follow these methods. Method 1. Unplug all external devices and restart the computer to check if this helps. Method 2.
Read more >
Windows 10 Black Screen after Update
1. Try a Windows Key Sequence to Wake the Screen: With this method, you will enable to computer to refresh the computer screen....
Read more >
Why am I seeing a "loading" image or a black screen?
Refresh /reload the live video player page (desktop/laptop users can use the keyboard shortcut, Ctrl + F5). Clear your cookies and cache data ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found