Video Syncronization Prototyping Complete.

This commit is contained in:
rainbow napkin 2025-01-15 06:29:12 -05:00
parent 0b68db1265
commit 6dc9ad7b34
10 changed files with 286 additions and 20 deletions

View file

@ -35,16 +35,19 @@ module.exports = class{
async handleConnection(userDB, chanDB, socket){
//send metadata to client
await this.sendClientMetadata();
this.sendClientMetadata();
//Send out emotes
await this.sendSiteEmotes();
await this.sendChanEmotes(chanDB);
await this.sendPersonalEmotes(userDB);
this.sendSiteEmotes();
this.sendChanEmotes(chanDB);
this.sendPersonalEmotes(userDB);
//Send out used tokes
await this.sendUsedTokes(userDB);
this.sendUsedTokes(userDB);
//Send out the currently playing item
this.channel.queue.sendQueue(socket);
//Tattoo hashed IP address to user account for seven days
await userDB.tattooIPRecord(socket.handshake.address);
}

View file

@ -23,22 +23,29 @@ module.exports = class{
this.server = server
//Set channel
this.channel = channel;
//Create variable to hold sync delta
//Create variable to hold sync delta in ms
this.syncDelta = 1000;
//Create variable to hold current timestamp within the video
this.timestamp = 0;
//Create variable to hold sync timer
this.syncTimer = null;
//Create variable to hold currently playing media object
this.nowPlaying = null;
//Create variable to hold current timestamp within the video
this.timestamp = 0;
}
queueMedia(inputMedia){
//Create new media object, start it now
//Create new media object, set start time to now
const mediaObj = queuedMedia.fromMedia(inputMedia, new Date().getTime());
//Start playback
this.play(mediaObj);
}
play(mediaObj){
//Silently end the media
this.end(true);
//reset current timestamp
this.timestamp = 0;
@ -46,7 +53,7 @@ module.exports = class{
this.nowPlaying = mediaObj;
//Send play signal out to the channel
this.server.io.in(this.channel.name).emit("play", {media: this.nowPlaying});
this.sendQueue();
//Kick off the sync timer
this.syncTimer = setTimeout(this.sync.bind(this), this.syncDelta);
@ -56,14 +63,58 @@ module.exports = class{
//Send sync signal out to the channel
this.server.io.in(this.channel.name).emit("sync", {timestamp: this.timestamp});
//If the media hasn't finished playing
if(this.timeStamp < this.nowPlaying.duration){
//If the media has over a second to go
if((this.timestamp + 1) < this.nowPlaying.duration){
//Increment the time stamp
this.timestamp++;
this.timestamp += (this.syncDelta / 1000);
//Call the sync function in another second
this.syncTimer = setTimeout(this.sync.bind(this), this.syncDelta);
}else{
//Get leftover video length in ms
const leftover = (this.nowPlaying.duration - this.timestamp) * 1000;
//Call the end function once the video is over
this.syncTimer = setTimeout(this.end.bind(this), leftover);
}
}
end(quiet = false){
//Call off any existing sync timer
clearTimeout(this.syncTimer);
//Clear out the sync timer
this.syncTimer = null;
//Clear now playing
this.nowPlaying = null;
//Clear timestamp
this.timestamp = 0;
//If we're not being quiet
if(!quiet){
//Tell everyone of the end-times
this.server.io.in(this.channel.name).emit('end', {});
}
}
sendQueue(socket){
//Create data object
const data = {
media: this.nowPlaying,
timestamp: this.timestamp
}
//If a socket is specified
if(socket != null){
//Send data out to specified socket
socket.emit("play", data);
//Otherwise
}else{
//Send that shit out to the entire channel
this.server.io.in(this.channel.name).emit("play", data);
}
}
}

View file

@ -72,7 +72,7 @@ module.exports = class{
const link = `https://archive.org/download/${mediaInfo.metadata.identifier}/${file.name}`
//Create new media object from file info
mediaList.push(new media(name, name, link, 'ia', file.length));
mediaList.push(new media(name, name, link, 'ia', Number(file.length)));
}
//return media object list

View file

@ -74,7 +74,7 @@ module.exports.fetchMetadata = async function(link){
function compatibilityFilter(file){
//return true for all files that match for web-safe formats
return file.format == "h.264"
return file.format == "h.264" || file.format == "Ogg Video" || file.format.match("MPEG4");
}
function pathFilter(file){

View file

@ -39,6 +39,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<script src="/js/channel/chatPostprocessor.js"></script>
<script src="/js/channel/chat.js"></script>
<script src="/js/channel/userlist.js"></script>
<script src="/js/channel/mediaHandler.js"></script>
<script src="/js/channel/player.js"></script>
<script src="/js/channel/cpanel.js"></script>
<script src="/js/channel/panels/emotePanel.js"></script>

View file

@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="media-panel" id="media-panel-div">
<div class="media-panel panel-head-div" id="media-panel-head-div">
<i class="media-panel panel-head-element bi-caret-down-fill" id="media-panel-div-toggle-icon"></i>
<p class="media-panel panel-head-element" id="media-panel-title-paragraph">Currently Playing: NULL</p>
<p class="media-panel panel-head-element" id="media-panel-title-paragraph">Currently Playing: <span id="media-panel-title-span">NULL</span></p>
<span class="media-panel panel-head-spacer-span" id="media-panel-head-spacer-span"></span>
<i class="media-panel panel-head-element bi-arrow-repeat" id="media-panel-sync-icon"></i>
<i class="media-panel panel-head-element bi-aspect-ratio-fill" id="media-panel-aspect-lock-icon"></i>
@ -27,5 +27,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<i class="media-panel panel-head-element bi-arrow-clockwise" id="media-panel-reload-icon"></i>
<i class="media-panel panel-head-element bi-chat-right-dots-fill" id="media-panel-show-chat-icon"></i>
</div>
<video src="/video/static.webm" class="media-panel" id="media-panel-video" muted loop autoplay></video>
<div id="media-panel-video-container">
</div>
</div>

View file

@ -13,6 +13,8 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<%# Technically favicon has nothing to do with .css, but it's still looks related, uses a link tag, and globally used :P %>
<link rel="icon" type="image/x-icon" href="/img/sweet_leaf_simple.png">
<link rel="stylesheet" href="/lib/bootstrap-icons/font/bootstrap-icons.css">
<link rel="stylesheet" type="text/css" href="/css/global.css">
<link rel="stylesheet" type="text/css" href="/css/flair.css">