Страница 6 из 16
Re: Google Home в качестве терминала
Добавлено: Пн май 21, 2018 5:24 pm
Gelezako
directman66 писал(а): Пн май 21, 2018 5:16 pm
Notifier установился? Как сервис висит? Случает порт?
На сколько я понял из кода всё что делает Notifier дак это предоставлять урл к мп3 для того что бы отсылать его на гугл хоум для воспроизведения. Ещё он может синтезировтаь мп3 из текста. Если вместо этого я буду использовать потоковое радио с МЖД, то Notifier тут как бы не нужен. Есть проблема именно работы гугл хоум как терминал для воспроизведения. Поправьте если я что-то не так понял.
Re: Google Home в качестве терминала
Добавлено: Пн май 21, 2018 7:19 pm
directman66
Без notifier вы не сможете ничего отправить на колонку, не разве что через bubbleUpnp. Сервис notifier выпольняет эмуляцию телефона на базе android и может давать команду воспроизвести mp3 или аудио-поток. Есть и другие подобные проекты, но у меня заработал только этот.
Re: Google Home в качестве терминала
Добавлено: Пн май 21, 2018 7:29 pm
Gelezako
directman66 писал(а): Пн май 21, 2018 7:19 pm
Сервис notifier выпольняет эмуляцию телефона на базе android и может давать команду воспроизвести mp3 или аудио-поток.
Очень сильно сомневаюсь что сервис эмулирует андроид. Всё что он делает дак это формирует HTTP ссылку на аудио-поток, которую можно скормить Google Home. Эмулировать Android тут нет необходимости, это уж очень геморно было бы.
Re: Google Home в качестве терминала
Добавлено: Пн май 21, 2018 8:24 pm
directman66
Если почитать код, там вроде используется библиотека node-castv2-client
https://github.com/thibauts/node-castv2 ... s/media.js
Re: Google Home в качестве терминала
Добавлено: Пн май 21, 2018 8:59 pm
Gelezako
а какое отношение эта библиотека имеет к Андроиду? Если прочитать описание:
This module implements a Chromecast client over the new (CASTV2) protocol. A sender app for the DefaultMediaReceiver application is provided, as well as an Application base class and implementations of the basic protocols (see the controllers directory) that should make implementing custom senders a breeze.
то можно понять что это имплементация протокола CASTV2, который работает в Chromecast.
Re: Google Home в качестве терминала
Добавлено: Пт июн 01, 2018 11:30 pm
dilligaf
Добрый день.
В обработчик before say не передается значение $filename.
В итоге yandex tts говорит, а на google-home уходит пустой url. Подскажите, есть решение?
Re: Google Home в качестве терминала
Добавлено: Пт июн 01, 2018 11:35 pm
skysilver
dilligaf писал(а): Пт июн 01, 2018 11:30 pm
Добрый день.
В обработчик before say не передается значение $filename.
В итоге yandex tts говорит, а на google-home уходит пустой url. Подскажите, есть решение?
Имя файла получают так:
Re: Google Home в качестве терминала
Добавлено: Пт июн 01, 2018 11:41 pm
dilligaf
Спасибо, да! Заменил на md5($ph), получилось
Re: Google Home в качестве терминала
Добавлено: Чт июн 21, 2018 6:35 am
directman66
Может у кого есть возможность портировать проект node.js
https://github.com/noelportugal/google-home-notifier в части отправки mp3 контента на устройство? Сейчас хотелось бы научиться использовать колонку google home без установки доп. сервисов.
Протокол, который используется в google-home-notifier описан в проекте
https://github.com/thibauts/node-castv2-client
Вроде есть пример
https://github.com/ChrisRidings/CastV2inPHP
В принципе и не так сложно, весь нужный нам функционал описан в файле media.js
Код: Выделить всё
var util = require('util');
var debug = require('debug')('castv2-client');
var RequestResponseController = require('./request-response');
function MediaController(client, sourceId, destinationId) {
RequestResponseController.call(this, client, sourceId, destinationId, 'urn:x-cast:com.google.cast.media');
this.currentSession = null;
this.on('message', onmessage);
this.once('close', onclose);
var self = this;
function onmessage(data, broadcast) {
if(data.type === 'MEDIA_STATUS' && broadcast) {
var status = data.status[0];
// Sometimes an empty status array can come through; if so don't emit it
if (!status) return;
self.currentSession = status;
self.emit('status', status);
}
}
function onclose() {
self.removeListener('message', onmessage);
self.stop();
}
}
util.inherits(MediaController, RequestResponseController);
MediaController.prototype.getStatus = function(callback) {
var self = this;
this.request({ type: 'GET_STATUS' }, function(err, response) {
if(err) return callback(err);
var status = response.status[0];
self.currentSession = status;
callback(null, status);
});
};
MediaController.prototype.load = function(media, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = { type: 'LOAD' };
data.autoplay = (typeof options.autoplay !== 'undefined')
? options.autoplay
: false;
data.currentTime = (typeof options.currentTime !== 'undefined')
? options.currentTime
: 0;
data.activeTrackIds = (typeof options.activeTrackIds !== 'undefined')
? options.activeTrackIds
: [];
data.repeatMode = (typeof options.repeatMode === "string" &&
typeof options.repeatMode !== 'undefined')
? options.repeatMode
: "REPEAT_OFF";
data.media = media;
this.request(data, function(err, response) {
if(err) return callback(err);
if(response.type === 'LOAD_FAILED') {
return callback(new Error('Load failed'));
}
if(response.type === 'LOAD_CANCELLED') {
return callback(new Error('Load cancelled'));
}
var status = response.status[0];
callback(null, status);
});
};
function noop() {}
MediaController.prototype.sessionRequest = function(data, callback) {
data.mediaSessionId = this.currentSession.mediaSessionId;
callback = callback || noop;
this.request(data, function(err, response) {
if(err) return callback(err);
var status = response.status[0];
callback(null, status);
});
};
MediaController.prototype.play = function(callback) {
this.sessionRequest({ type: 'PLAY' }, callback);
};
MediaController.prototype.pause = function(callback) {
this.sessionRequest({ type: 'PAUSE' }, callback);
};
MediaController.prototype.stop = function(callback) {
this.sessionRequest({ type: 'STOP' }, callback);
};
MediaController.prototype.seek = function(currentTime, callback) {
var data = {
type: 'SEEK',
currentTime: currentTime
};
this.sessionRequest(data, callback);
};
//Load a queue of items to play (playlist)
//See https://developers.google.com/cast/docs/reference/chrome/chrome.cast.media.QueueLoadRequest
MediaController.prototype.queueLoad = function(items, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = { type: 'QUEUE_LOAD' };
//REPEAT_OFF, REPEAT_ALL, REPEAT_SINGLE, REPEAT_ALL_AND_SHUFFLE
data.repeatMode = (typeof options.repeatMode === "string" &&
typeof options.repeatMode !== 'undefined')
? options.repeatMode
: "REPEAT_OFF";
data.currentTime = (typeof options.currentTime !== 'undefined')
? options.currentTime
: 0;
data.startIndex = (typeof options.startIndex !== 'undefined')
? options.startIndex
: 0;
data.items = items;
this.request(data, function(err, response) {
if(err) return callback(err);
if(response.type === 'LOAD_FAILED') {
return callback(new Error('queueLoad failed'));
}
if(response.type === 'LOAD_CANCELLED') {
return callback(new Error('queueLoad cancelled'));
}
var status = response.status[0];
callback(null, status);
});
};
MediaController.prototype.queueInsert = function(items, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = {
type: 'QUEUE_INSERT',
currentItemId: options.currentItemId, //Item ID to play after this request or keep same item if undefined
currentItemIndex: options.currentItemIndex, //Item Index to play after this request or keep same item if undefined
currentTime: options.currentTime, //Seek in seconds for current stream
insertBefore: options.insertBefore, //ID or append if undefined
items: items
};
this.sessionRequest(data, callback);
};
MediaController.prototype.queueRemove = function(itemIds, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = {
type: 'QUEUE_REMOVE',
currentItemId: options.currentItemId,
currentTime: options.currentTime,
itemIds: itemIds
};
this.sessionRequest(data, callback);
};
MediaController.prototype.queueReorder = function(itemIds, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = {
type: 'QUEUE_REORDER',
currentItemId: options.currentItemId,
currentTime: options.currentTime,
insertBefore: options.insertBefore,
itemIds: itemIds
};
this.sessionRequest(data, callback);
};
MediaController.prototype.queueUpdate = function(items, options, callback) {
if(typeof options === 'function' || typeof options === 'undefined') {
callback = options;
options = {};
}
var data = {
type: 'QUEUE_UPDATE',
currentItemId: options.currentItemId,
currentTime: options.currentTime,
jump: options.jump, //Skip or go back (if negative) number of items
repeatMode: options.repeatMode,
items: items
};
this.sessionRequest(data, callback);
};
module.exports = MediaController;
Также имеется задача интеграции majordomo и google assistant в идеях Разработки ядра системы MajorDoMo и звучит "Добавить поддержку Google Home без использования стороннего кода", пока набрала только 5 голосов
https://connect.smartliving.ru/tasks/1.html
Просьба проголосовать за необходимый функционал.
А самое интересное, что из media.js можно сделать вывод, что протоколом castv2 предусмотрена команда добавления в очередь вопроизведения, очиста очереди!!! Также есть управление громкостью и т.д.
В общем пора создавать свой клас для управления на php.
Из того, что важно:
contentType: 'audio/mp3',
streamType: 'BUFFERED' // or LIVE
player.load(media, { autoplay: true }, function(err, status) {
Re: Google Home в качестве терминала
Добавлено: Чт июн 21, 2018 8:09 pm
directman66
Друзья! Google Home теперь может выступать в качестве терминала без установки доп. софта.
В терминале выбираем Chromcast/google TV, вводим ip адрес и все!!! Колонка будет штатно производить требуемый контент.
Единственный момент, пока не реализована подписка на команду say, поэтому временно осталвяем beforesay:
Код: Выделить всё
$url='http://192.168.1.39/cms/cached/voice/'.basename($filename); if((basename($filename)<>"dingdong.mp3")and (gg("NightMode.active")<>"1")) {playMedia($url,'MAIN'); sg('test.play',$url); }
____
upd: Ну или я погорячился. Один раз сработало и теперь молчит. Разбираюсь.