Browse Source

Start

master
Foreman 5 months ago
commit
7afa2f350d
  1. 2
      .gitignore
  2. 152
      index.js
  3. BIN
      music/a-hero-of-the-80s-126684.mp3
  4. BIN
      music/game-background-359782.mp3
  5. BIN
      music/hypernova-cascade-363576.mp3
  6. 1
      music/srcs.txt
  7. 1614
      package-lock.json
  8. 17
      package.json

2
.gitignore vendored

@ -0,0 +1,2 @@
*.mp4
node_modules/

152
index.js

@ -0,0 +1,152 @@
// index.js
const puppeteer = require('puppeteer');
const { PuppeteerScreenRecorder } = require('puppeteer-screen-recorder');
const ffmpeg = require('fluent-ffmpeg');
const getVideoDurationInSeconds = require('get-video-duration').getVideoDurationInSeconds;
async function rotateVideo(inputPath, outputPath) {
// Get original duration
const originalDuration = await getVideoDurationInSeconds(inputPath);
const targetDuration = 30;
const speedFactor = originalDuration / targetDuration;
return new Promise((resolve, reject) => {
ffmpeg(inputPath)
.videoFilters([
{ filter: 'crop', options: '1920:1080:0:0' },
{ filter: 'transpose', options: '2' },
{ filter: 'setpts', options: `PTS/${speedFactor}` }
])
// Optional: speed up audio as well (max 2x per atempo, so chain if needed)
.audioFilters(
speedFactor <= 2
? { filter: 'atempo', options: speedFactor }
: [
{ filter: 'atempo', options: 2 },
{ filter: 'atempo', options: speedFactor / 2 }
]
)
.save(outputPath)
.on('end', () => {
console.log('Crop, rotation, and speed-up complete!');
resolve();
})
.on('error', err => reject(err));
});
}
function addMusicToVideo(videoPath, musicPath, outputPath, musicVolume = 0.1) {
return new Promise((resolve, reject) => {
ffmpeg()
.addInput(videoPath)
.addInput(musicPath)
.complexFilter([
// If your video has NO audio, just set the music volume and map
'[1:a]volume=' + musicVolume + '[aud]'
])
.outputOptions([
'-map 0:v', // video from first input
'-map [aud]', // audio from [aud]
'-shortest', // end when shortest ends
'-c:v copy' // copy video, do not re-encode
])
.save(outputPath)
.on('end', () => {
console.log('Music added and volume set!');
resolve();
})
.on('error', reject);
});
}
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
// Set to vertical/portrait mode
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 1,
});
await page.goto('https://tacticfront.io/join/aQoyBBX7');
// Click "Pause game" on load
await page.waitForSelector('button[title="Pause game"]');
await page.click('button[title="Pause game"]');
console.log('Game paused. Waiting for unpause (second click)...');
// Set up a promise in Node
const clickedPromise = new Promise(resolve => {
page.exposeFunction('notifyPauseButtonClicked', resolve);
});
// Attach a page-wide click handler in the browser context
await page.evaluate(() => {
// Remove any existing listener for safety
window._pauseButtonHandler && document.removeEventListener('click', window._pauseButtonHandler);
window._pauseButtonHandler = function (e) {
if (
e.target &&
e.target.tagName === 'BUTTON' &&
e.target.title === 'Pause game'
) {
window.notifyPauseButtonClicked();
document.removeEventListener('click', window._pauseButtonHandler); // Only once
}
};
document.addEventListener('click', window._pauseButtonHandler);
});
console.log('Game paused. Waiting for unpause (manual click)...');
await clickedPromise;
// Start recording
console.log("Recorder Start")
const recorder = new PuppeteerScreenRecorder(page);
await recorder.start('./replay.mp4');
// Stop recording on game end
let recordingStopped = false;
async function finishRecording() {
if (!recordingStopped) {
recordingStopped = true;
await recorder.stop();
await browser.close();
// Now rotate the video
await rotateVideo('replay.mp4', 'output_vertical.mp4');
await addMusicToVideo('output_vertical.mp4', './music/a-hero-of-the-80s-126684.mp3', 'final_output.mp4', 0.05);
}
}
page.on('console', async msg => {
if (msg.text().includes('local server ending game')) {
console.log('Detected "local server ending game" in console. Stopping recording...');
await finishRecording();
}
});
setTimeout(async () => {
if (!recordingStopped) {
console.log('Timeout reached. Stopping recording...');
await finishRecording();
}
}, 10 * 60 * 1000); // 5 minutes
})();
// Spina has won the game
//local server ending game

BIN
music/a-hero-of-the-80s-126684.mp3

Binary file not shown.

BIN
music/game-background-359782.mp3

Binary file not shown.

BIN
music/hypernova-cascade-363576.mp3

Binary file not shown.

1
music/srcs.txt

@ -0,0 +1 @@
https://pixabay.com/music/search/genre/video%20games/?pagi=2

1614
package-lock.json generated

File diff suppressed because it is too large Load Diff

17
package.json

@ -0,0 +1,17 @@
{
"name": "replayrecorder",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"fluent-ffmpeg": "^2.1.3",
"get-video-duration": "^4.1.0",
"puppeteer": "^24.10.2",
"puppeteer-screen-recorder": "^3.0.6"
}
}
Loading…
Cancel
Save