Audio crash fixes
This commit is contained in:
@@ -22,9 +22,13 @@ RUN apk add --no-cache \
|
|||||||
|
|
||||||
# Download and extract Weatherscan music
|
# Download and extract Weatherscan music
|
||||||
RUN mkdir -p /music && \
|
RUN mkdir -p /music && \
|
||||||
|
echo "Downloading Weatherscan music..." && \
|
||||||
wget -O /tmp/weatherscan.zip "https://archive.org/compress/weatherscancompletecollection/formats=OGG%20VORBIS&file=/weatherscancompletecollection.zip" && \
|
wget -O /tmp/weatherscan.zip "https://archive.org/compress/weatherscancompletecollection/formats=OGG%20VORBIS&file=/weatherscancompletecollection.zip" && \
|
||||||
|
echo "Extracting OGG files..." && \
|
||||||
unzip -j /tmp/weatherscan.zip "*.ogg" -d /music && \
|
unzip -j /tmp/weatherscan.zip "*.ogg" -d /music && \
|
||||||
rm /tmp/weatherscan.zip
|
echo "Music files extracted: $(ls -1 /music/*.ogg | wc -l) files" && \
|
||||||
|
rm /tmp/weatherscan.zip && \
|
||||||
|
echo "Weatherscan music setup complete!"
|
||||||
|
|
||||||
# Set Puppeteer to use installed Chromium
|
# Set Puppeteer to use installed Chromium
|
||||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
|
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
|
||||||
|
|||||||
27
index.js
27
index.js
@@ -124,19 +124,24 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
if (useMusic) {
|
if (useMusic) {
|
||||||
// Get all music files and shuffle them
|
// Get all music files and shuffle them
|
||||||
const allMusicFiles = getAllMusicFiles();
|
const allMusicFiles = getAllMusicFiles();
|
||||||
if (allMusicFiles.length > 0 && allMusicFiles.length > 0) {
|
console.log(`Found ${allMusicFiles.length} music files in ${MUSIC_PATH}`);
|
||||||
|
if (allMusicFiles.length > 0) {
|
||||||
// Create a temporary concat playlist file
|
// Create a temporary concat playlist file
|
||||||
playlistFile = path.join('/tmp', `playlist-${Date.now()}.txt`);
|
playlistFile = path.join('/tmp', `playlist-${Date.now()}.txt`);
|
||||||
|
|
||||||
// Build playlist content - repeat the list 3 times to reduce loop edge case issues
|
// Build playlist content - repeat enough times for ~24 hours of playback
|
||||||
|
// Assuming avg 3 min per track, repeat enough to cover a full day
|
||||||
const currentShuffle = shuffleArray([...allMusicFiles]);
|
const currentShuffle = shuffleArray([...allMusicFiles]);
|
||||||
|
const repetitions = Math.max(20, Math.ceil(480 / allMusicFiles.length)); // At least 480 tracks (~24hrs)
|
||||||
const playlistLines = [];
|
const playlistLines = [];
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < repetitions; i++) {
|
||||||
currentShuffle.forEach(f => playlistLines.push(`file '${f}'`));
|
// Re-shuffle each repetition for more variety
|
||||||
|
const shuffled = shuffleArray([...allMusicFiles]);
|
||||||
|
shuffled.forEach(f => playlistLines.push(`file '${f}'`));
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(playlistFile, playlistLines.join('\n'));
|
fs.writeFileSync(playlistFile, playlistLines.join('\n'));
|
||||||
// console.log(`Created shuffled playlist with ${allMusicFiles.length} tracks x3 repetitions (infinite loop)`);
|
// console.log(`Created playlist with ${allMusicFiles.length} tracks x${repetitions} repetitions (~${playlistLines.length} total tracks)`);
|
||||||
|
|
||||||
// Input 0: video frames
|
// Input 0: video frames
|
||||||
ffmpegArgs.push(
|
ffmpegArgs.push(
|
||||||
@@ -149,7 +154,6 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
ffmpegArgs.push(
|
ffmpegArgs.push(
|
||||||
'-f', 'concat',
|
'-f', 'concat',
|
||||||
'-safe', '0',
|
'-safe', '0',
|
||||||
'-stream_loop', '-1', // Loop playlist infinitely
|
|
||||||
'-i', playlistFile
|
'-i', playlistFile
|
||||||
);
|
);
|
||||||
// Encoding with audio filtering for smooth transitions
|
// Encoding with audio filtering for smooth transitions
|
||||||
@@ -314,7 +318,7 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
console.log('Page network idle, waiting for content to render...');
|
console.log('Page network idle, waiting for content to render...');
|
||||||
|
|
||||||
// Additional wait for dynamic content to fully render (weather data, radar, etc.)
|
// Additional wait for dynamic content to fully render (weather data, radar, etc.)
|
||||||
await page.waitForTimeout(3000);
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||||
|
|
||||||
// Verify content is actually visible before switching
|
// Verify content is actually visible before switching
|
||||||
const hasVisibleContent = await page.evaluate(() => {
|
const hasVisibleContent = await page.evaluate(() => {
|
||||||
@@ -332,7 +336,7 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
|
|
||||||
if (!hasVisibleContent) {
|
if (!hasVisibleContent) {
|
||||||
console.log('Content not fully visible yet, waiting additional time...');
|
console.log('Content not fully visible yet, waiting additional time...');
|
||||||
await page.waitForTimeout(2000);
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Page fully loaded with all resources, switching to live frames');
|
console.log('Page fully loaded with all resources, switching to live frames');
|
||||||
@@ -378,12 +382,15 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
if (!isCleaningUp && page && !page.isClosed() && updatedUrl && updatedUrl !== url) {
|
if (!isCleaningUp && page && !page.isClosed() && updatedUrl && updatedUrl !== url) {
|
||||||
try {
|
try {
|
||||||
console.log('Updating to correct location...');
|
console.log('Updating to correct location...');
|
||||||
|
// Ensure black frames continue during navigation
|
||||||
|
sendBlackFrames = true;
|
||||||
|
|
||||||
// Wait for networkidle2 to ensure all resources load
|
// Wait for networkidle2 to ensure all resources load
|
||||||
await page.goto(updatedUrl, { waitUntil: 'networkidle2', timeout: 45000 });
|
await page.goto(updatedUrl, { waitUntil: 'networkidle2', timeout: 45000 });
|
||||||
console.log('Correct location network idle, waiting for content...');
|
console.log('Correct location network idle, waiting for content...');
|
||||||
|
|
||||||
// Additional wait for dynamic content
|
// Additional wait for dynamic content
|
||||||
await page.waitForTimeout(3000);
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||||
|
|
||||||
// Verify content is visible
|
// Verify content is visible
|
||||||
const hasVisibleContent = await page.evaluate(() => {
|
const hasVisibleContent = await page.evaluate(() => {
|
||||||
@@ -398,7 +405,7 @@ async function streamHandler(req, res, useMusic = false, lateGeocodePromise = nu
|
|||||||
|
|
||||||
if (!hasVisibleContent) {
|
if (!hasVisibleContent) {
|
||||||
console.log('Content not fully visible yet, waiting additional time...');
|
console.log('Content not fully visible yet, waiting additional time...');
|
||||||
await page.waitForTimeout(2000);
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Correct location fully loaded, switching to live frames');
|
console.log('Correct location fully loaded, switching to live frames');
|
||||||
|
|||||||
Reference in New Issue
Block a user