Skip to main content
Participant
September 28, 2024
Question

Automatic renders of compisitions with text

  • September 28, 2024
  • 4 replies
  • 249 views

I have a project that consists of three codes, the project is based on having a website hosted on localhost and changing two texts of a composition from that website so that the video is automatically rendered.
But I have a problem and it is that the render does it but without changing the texts.
Does anyone know how to fix it?

Index.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Renderizar Video</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        input {
            margin: 5px;
            padding: 10px;
            width: 300px;
        }
        button {
            padding: 10px 20px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <h1>Renderizar Video con Textos</h1>
    <label for="nom">Nom:</label>
    <input type="text" id="nom" placeholder="Introduce Nom"><br>

    <label for="xarxes">Xarxes:</label>
    <input type="text" id="xarxes" placeholder="Introduce Xarxes"><br>

    <button id="renderButton">Render</button>

    <script>
        document.getElementById('renderButton').addEventListener('click', function() {
            const nom = document.getElementById('nom').value;
            const xarxes = document.getElementById('xarxes').value;

            console.log('Datos enviados:', { nom, xarxes }); // Verifica los datos en la consola

            fetch('http://localhost:8001/render', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ nom, xarxes })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Error en la solicitud: ' + response.statusText);
                }
                return response.text();
            })
            .then(data => {
                console.log('Respuesta del servidor:', data); // Muestra la respuesta del servidor
                alert('Renderizado iniciado');
            })
            .catch(error => {
                console.error('Error:', error);
                alert('Hubo un error: ' + error.message);
            });
        });
    </script>
</body>
</html>

 

server.js

const http = require('http');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/render') {
        let body = '';
        req.on('data', chunk => {
            body += chunk.toString(); // Convertir Buffer a string
        });
        req.on('end', () => {
            try {
                const { nom, xarxes } = JSON.parse(body);
                console.log(`Renderizando con Nom: ${nom} y Xarxes: ${xarxes}`);

                // Ruta del archivo del proyecto After Effects
                const projectFilePath = "F:/OBS/Chyrons/Chyrons.aep";

                // Ruta donde se guardará el archivo renderizado
                const renderFolderPath = "F:/OBS/Chyrons/Render";
                
                // Crear nombre de archivo de salida
                const outputFileName = `CHY_DER_${nom}_${xarxes}.mov`;
                const outputFilePath = `${renderFolderPath}/${outputFileName}`;

                // Crear un archivo JSX temporal con los datos para reemplazar textos
                const jsxScript = `
                    var projectFilePath = "${projectFilePath.replace(/\\/g, "/")}";
                    var renderFolderPath = "${renderFolderPath.replace(/\\/g, "/")}";
                    var nom = "${nom}";
                    var xarxes = "${xarxes}";

                    function updateTextsInComp(comp, nom, xarxes) {
                        var nomFound = false;
                        var xarxesFound = false;

                        for (var i = 1; i <= comp.numLayers; i++) {
                            var layer = comp.layer(i);
                            if (layer.property("Source Text") != null) {
                                if (layer.name === "Nom") {
                                    layer.property("Source Text").setValue(nom);
                                    $.writeln("Texto de Nom actualizado a: " + nom);
                                    nomFound = true;
                                } else if (layer.name === "Xarxes") {
                                    layer.property("Source Text").setValue(xarxes);
                                    $.writeln("Texto de Xarxes actualizado a: " + xarxes);
                                    xarxesFound = true;
                                }
                            }
                        }

                        if (!nomFound) {
                            $.writeln("No se encontró la capa 'Nom'.");
                        }
                        if (!xarxesFound) {
                            $.writeln("No se encontró la capa 'Xarxes'.");
                        }
                    }

                    function renderComp(comp) {
                        app.project.renderQueue.items.removeAll(); // Limpiar cola de renderizado
                        var renderQueueItem = app.project.renderQueue.items.add(comp); // Añadir la composición a la cola
                        var outputModule = renderQueueItem.outputModule(1); // Obtener el primer módulo de salida
                        
                        var outputFilePath = new File(renderFolderPath + "/" + "CHY_DER_" + nom + "_" + xarxes + ".mov");
                        outputModule.file = outputFilePath; // Configurar la ruta de salida

                        $.writeln("Archivo de salida configurado en: " + outputFilePath.fsName); // Mensaje de depuración
                        app.project.renderQueue.render(); // Comienza el renderizado
                    }

                    function main() {
                        app.open(new File(projectFilePath)); // Abrir el proyecto
                        $.writeln("Proyecto abierto: " + projectFilePath);

                        var comp = null;
                        for (var i = 1; i <= app.project.numItems; i++) {
                            if (app.project.item(i).name === "CHY_DER_Persona") {
                                comp = app.project.item(i); // Encontrar la composición
                                break;
                            }
                        }

                        if (comp == null) {
                            $.writeln("Error: Composición CHY_DER_Persona no encontrada.");
                            alert("Composición CHY_DER_Persona no encontrada");
                            return;
                        }

                        updateTextsInComp(comp, nom, xarxes); // Actualizar textos
                        renderComp(comp); // Renderizar la composición
                    }

                    main();
                `;

                // Guardar el archivo JSX temporalmente
                const jsxFilePath = path.join(__dirname, 'temp_render_script.jsx');
                fs.writeFileSync(jsxFilePath, jsxScript);

                // Comando para aerender
                const pathToAerender = `"C:\\Program Files\\Adobe\\Adobe After Effects 2023\\Support Files\\aerender.exe"`;

                // Ejecutar aerender con el proyecto, la composición y la salida
                exec(`${pathToAerender} -project "${projectFilePath}" -comp "CHY_DER_Persona" -output "${outputFilePath}"`, (error, stdout, stderr) => {
                    if (error) {
                        console.error(`Error al ejecutar aerender: ${error.message}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error al renderizar: ${error.message}`);
                        return;
                    }
                    if (stderr) {
                        console.error(`stderr: ${stderr}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error en el script: ${stderr}`);
                        return;
                    }
                    console.log(`stdout: ${stdout}`);
                    res.writeHead(200, { 'Content-Type': 'text/plain' });
                    res.end('Renderizado iniciado');

                    // Limpiar el archivo JSX temporal
                    fs.unlinkSync(jsxFilePath);
                });

            } catch (e) {
                console.error(`Error al procesar JSON: ${e}`);
                res.writeHead(400, { 'Content-Type': 'text/plain' });
                res.end('Datos inválidos');
            }
        });
    } else {
        let filePath = path.join(__dirname, req.url === '/' ? 'index.html' : req.url);
        let extname = String(path.extname(filePath)).toLowerCase();
        let mimeTypes = {
            '.html': 'text/html',
            '.js': 'text/javascript',
            '.css': 'text/css',
            '.json': 'application/json',
        };

        let contentType = mimeTypes[extname] || 'application/octet-stream';

        fs.readFile(filePath, (error, content) => {
            if (error) {
                if (error.code == 'ENOENT') {
                    res.writeHead(404, { 'Content-Type': 'text/html' });
                    res.end('<h1>404 Not Found</h1>', 'utf-8');
                } else {
                    res.writeHead(500);
                    res.end('Sorry, there was an error: ' + error.code + '..\n');
                }
            } else {
                res.writeHead(200, { 'Content-Type': contentType });
                res.end(content, 'utf-8');
            }
        });
    }
});

const PORT = 8001;
server.listen(PORT, () => {
    console.log(`Servidor corriendo en http://localhost:${PORT}`);
});

 

your_script.jsx

// URL del servidor para recibir los datos
var projectFilePath = "F:/OBS/Chyrons/Chyrons.aep";
var renderFolderPath = "F:/OBS/Chyrons/Render";

// Obtener los argumentos pasados desde el servidor
var nom = app.project.renderQueue.arguments[0]; // Primer argumento
var xarxes = app.project.renderQueue.arguments[1]; // Segundo argumento

// Asegúrate de que los argumentos son válidos
if (!nom || !xarxes) {
    alert("No se pasaron valores correctos para nom y xarxes.");
    return;
}

// Función para actualizar los textos en la composición
function updateTextsInComp(comp, nom, xarxes) {
    for (var i = 1; i <= comp.numLayers; i++) {
        var layer = comp.layer(i);
        if (layer.property("Source Text") != null) {
            if (layer.name === "Nom") {
                layer.property("Source Text").setValue(nom);
                $.writeln("Texto de Nom actualizado a: " + nom);
            } else if (layer.name === "Xarxes") {
                layer.property("Source Text").setValue(xarxes);
                $.writeln("Texto de Xarxes actualizado a: " + xarxes);
            }
        }
    }
}

// Función para renderizar la composición
function renderComp(comp) {
    app.project.renderQueue.items.removeAll(); // Limpiar la cola de renderizado
    var renderQueueItem = app.project.renderQueue.items.add(comp); // Añadir la composición a la cola
    var outputModule = renderQueueItem.outputModule(1); // Obtener el primer módulo de salida

    // Configurar el archivo de salida
    var outputFilePath = new File(renderFolderPath + "/" + "CHY_DER_" + nom + "_" + xarxes + ".mov");
    outputModule.file = outputFilePath;

    // Comienza el renderizado
    app.project.renderQueue.render();
}

// Función principal
function main() {
    app.open(new File(projectFilePath)); // Abrir el proyecto

    var comp = null;
    for (var i = 1; i <= app.project.numItems; i++) {
        if (app.project.item(i).name === "CHY_DER_Persona") {
            comp = app.project.item(i); // Encontrar la composición
            break;
        }
    }

    if (comp == null) {
        alert("Composición CHY_DER_Persona no encontrada");
        return;
    }

    updateTextsInComp(comp, nom, xarxes); // Actualizar textos
    renderComp(comp); // Renderizar la composición
}

main();

 

Thank you very much for reading and trying to help.
Martí Franquesa

This topic has been closed for replies.

4 replies

Participant
September 29, 2024

Thank you very much for your help. I’m currently trying to auto-render two compositions, but only one of them is working (form.html); the other one gives me an error. I'll include all the code and a picture below.
Thanks again!

 

 

index.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Redirección a CHY_Persona</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            text-align: center;
        }
        button {
            padding: 15px 30px;
            font-size: 20px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>Bienvenido</h1>
    <button id="chyPersonaButton">CHY_Persona</button>
    <button id="titularButton">Titular</button> <!-- Nuevo botón para Titular -->

    <script>
        document.getElementById('chyPersonaButton').addEventListener('click', function() {
            window.location.href = 'form.html'; // Cambiar a la URL donde estaba el contenido anterior
        });
        
        // Redireccionar a la nueva página de Titular
        document.getElementById('titularButton').addEventListener('click', function() {
            window.location.href = 'titular.html'; // Nueva URL para Titular
        });
    </script>
</body>
</html>

 

 

form.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Renderizar Video</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        input {
            margin: 5px;
            padding: 10px;
            width: 300px;
        }
        button {
            padding: 10px 20px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <h1>Renderizar Video con Textos</h1>
    <label for="nom">Nom:</label>
    <input type="text" id="nom" placeholder="Introduce Nom"><br>

    <label for="xarxes">Xarxes:</label>
    <input type="text" id="xarxes" placeholder="Introduce Xarxes"><br>

    <label for="direction">Dirección:</label>
    <select id="direction">
        <option value="derecha">Derecha</option>
        <option value="izquierda">Izquierda</option>
    </select><br>

    <button id="renderButton">Render</button>

    <script>
        document.getElementById('renderButton').addEventListener('click', function() {
            const nom = document.getElementById('nom').value;
            const xarxes = document.getElementById('xarxes').value;
            const direction = document.getElementById('direction').value;
    
            console.log('Datos enviados:', { nom, xarxes, direction }); // Verifica los datos en la consola
    
            fetch('http://localhost:8001/render', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ nom, xarxes, direction })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Error en la solicitud: ' + response.statusText);
                }
                return response.text();
            })
            .then(data => {
                console.log('Respuesta del servidor:', data); // Muestra la respuesta del servidor
                alert('Renderizado iniciado');
            })
            .catch(error => {
                console.error('Error:', error);
                alert('Hubo un error: ' + error.message);
            });
        });
    </script>
</body>
</html>

 

 

titular.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Renderizar Titular</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        input {
            margin: 5px;
            padding: 10px;
            width: 300px;
        }
        button {
            padding: 10px 20px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <h1>Renderizar Video con Titular</h1>
    <label for="titularTxt">Titular:</label>
    <input type="text" id="titularTxt" placeholder="Introduce el Titular"><br>

    <button id="renderTitularButton">Renderizar</button>

    <script>
        document.getElementById('renderTitularButton').addEventListener('click', function() {
            const titularTxt = document.getElementById('titularTxt').value;

            console.log('Datos enviados:', { titularTxt }); // Verifica los datos en la consola

            fetch('http://localhost:8001/renderTitular', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ titularTxt })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Error en la solicitud: ' + response.statusText);
                }
                return response.text();
            })
            .then(data => {
                console.log('Respuesta del servidor:', data); // Muestra la respuesta del servidor
                alert('Renderizado de Titular iniciado');
            })
            .catch(error => {
                console.error('Error:', error);
                alert('Hubo un error: ' + error.message);
            });
        });
    </script>
</body>
</html>

 

 

server.js

const http = require('http');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/render') {
        let body = '';
        req.on('data', chunk => {
            body += chunk.toString(); // Convertir Buffer a string
        });
        req.on('end', () => {
            try {
                const { nom, xarxes, direction, type } = JSON.parse(body);
                console.log(`Renderizando con Nom: ${nom}, Xarxes: ${xarxes}, Dirección: ${direction}, Tipo: ${type}`);

                // Ruta del archivo del proyecto After Effects
                const projectFilePath = "F:/OBS/Chyrons/Chyrons.aep";
                const renderFolderPath = "F:/OBS/Chyrons/Render";

                // Crear nombre de archivo de salida
                const outputFileName = type === 'Titular' 
                    ? `Titular_${nom}.mov` 
                    : `CHY_${direction === 'derecha' ? 'DER' : 'IZQ'}_${nom}_${xarxes}.mov`;
                
                const outputFilePath = `${renderFolderPath}/${outputFileName}`;

                // Crear un archivo JSX temporal con los datos para reemplazar textos
                const jsxScript = `
                var projectFilePath = "${projectFilePath.replace(/\\/g, " / ")}";
                var renderFolderPath = "${renderFolderPath.replace(/\\/g, " / ")}";
                var nom = "${nom}";
                var xarxes = "${xarxes}";
                var direction = "${direction}";
                var type = "${type}"; // Asegúrate de que la variable 'type' se defina aquí
                
                function updateTextsInComp(comp, nom, xarxes) {
                    var nomFound = false;
                    var xarxesFound = false;
                
                    for (var i = 1; i <= comp.numLayers; i++) {
                        var layer = comp.layer(i);
                        if (layer.property("Source Text") != null) {
                            if (layer.name === "Nom") {
                                layer.property("Source Text").setValue(nom);
                                $.writeln("Texto de Nom actualizado a: " + nom);
                                nomFound = true;
                            } else if (layer.name === "Xarxes") {
                                layer.property("Source Text").setValue(xarxes);
                                $.writeln("Texto de Xarxes actualizado a: " + xarxes);
                                xarxesFound = true;
                            }
                        }
                    }
                
                    if (!nomFound) {
                        $.writeln("No se encontró la capa 'Nom'.");
                    }
                    if (!xarxesFound) {
                        $.writeln("No se encontró la capa 'Xarxes'.");
                    }
                }
                
                function renderComp(comp) {
                    // Limpiar la cola de renderizado
                    while (app.project.renderQueue.numItems > 0) {
                        app.project.renderQueue.items[1].remove(); // Eliminar el primer elemento
                    }
                    
                    var renderQueueItem = app.project.renderQueue.items.add(comp); // Añadir la composición a la cola
                    var outputModule = renderQueueItem.outputModule(1); // Obtener el primer módulo de salida
                
                    // Configurar el archivo de salida
                    var outputFilePath = new File(renderFolderPath + "/" + "${outputFileName}");
                    outputModule.file = outputFilePath; // Configurar la ruta de salida
                
                    // Comienza el renderizado
                    app.project.renderQueue.render();
                }
                
                function main() {
                    app.open(new File(projectFilePath)); // Abrir el proyecto
                
                    var comp = null;
                    if (type === 'Titular') {
                        comp = app.project.item(1); // Asume que la primera composición es 'Titular'
                    } else {
                        var compName = direction === 'derecha' ? "CHY_DER_Persona" : "CHY_IZQ_Persona";
                        for (var i = 1; i <= app.project.numItems; i++) {
                            if (app.project.item(i).name === compName) {
                                comp = app.project.item(i); // Encontrar la composición
                                break;
                            }
                        }
                    }
                
                    if (comp == null) {
                        $.writeln("Error: Composición no encontrada.");
                        alert("Composición no encontrada");
                        return;
                    }
                
                    if (type === 'Titular') {
                        updateTextsInComp(comp, nom, ""); // Solo actualiza el 'Nom'
                    } else {
                        updateTextsInComp(comp, nom, xarxes); // Actualizar textos
                    }
                
                    renderComp(comp); // Renderizar la composición
                }
                
                main();
                app.executeCommand(5); // Guardar automáticamente
                `;
                


                // Guardar el archivo JSX temporalmente
                const jsxFilePath = path.join(__dirname, 'temp_render_script.jsx');
                fs.writeFileSync(jsxFilePath, jsxScript);

                // Comando para aerender
                const pathToAerender = `"C:\\Program Files\\Adobe\\Adobe After Effects 2023\\Support Files\\afterfx.exe"`;

                // Ejecutar aerender con el proyecto, la composición y la salida
                exec(`${pathToAerender} -s $.evalFile("${jsxFilePath.replace(/\\/g, "/")}")`, (error, stdout, stderr) => {
                    if (error) {
                        console.error(`Error al ejecutar aerender: ${error.message}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error al renderizar: ${error.message}`);
                        return;
                    }
                    if (stderr) {
                        console.error(`stderr: ${stderr}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error en el script: ${stderr}`);
                        return;
                    }
                    console.log(`stdout: ${stdout}`);
                    res.writeHead(200, { 'Content-Type': 'text/plain' });
                    res.end('Renderizado iniciado');

                    // Limpiar el archivo JSX temporal
                    fs.unlinkSync(jsxFilePath);
                });

            } catch (e) {
                console.error(`Error al procesar JSON: ${e}`);
                res.writeHead(400, { 'Content-Type': 'text/plain' });
                res.end('Datos inválidos');
            }
        });
    } else {
        let filePath = path.join(__dirname, req.url === '/' ? 'index.html' : req.url);
        let extname = String(path.extname(filePath)).toLowerCase();
        let mimeTypes = {
            '.html': 'text/html',
            '.js': 'text/javascript',
            '.css': 'text/css',
            '.json': 'application/json',
        };

        let contentType = mimeTypes[extname] || 'application/octet-stream';

        fs.readFile(filePath, (error, content) => {
            if (error) {
                if (error.code == 'ENOENT') {
                    res.writeHead(404, { 'Content-Type': 'text/html' });
                    res.end('<h1>404 Not Found</h1>', 'utf-8');
                } else {
                    res.writeHead(500);
                    res.end('Sorry, there was an error: ' + error.code + '..\n');
                }
            } else {
                res.writeHead(200, { 'Content-Type': contentType });
                res.end(content, 'utf-8');
            }
        });
    }
});

const PORT = 8001;
server.listen(PORT, () => {
    console.log(`Servidor corriendo en http://localhost:${PORT}`);
});

 

 

your_script.jsx

// URL del servidor para recibir los datos
var projectFilePath = "F:/OBS/Chyrons/Chyrons.aep";
var renderFolderPath = "F:/OBS/Chyrons/Render";

// Obtener los argumentos pasados desde el servidor
var nom = app.project.renderQueue.arguments[0]; // Primer argumento
var xarxes = app.project.renderQueue.arguments[1]; // Segundo argumento

// Asegúrate de que los argumentos son válidos
if (!nom || !xarxes) {
    alert("No se pasaron valores correctos para nom y xarxes.");
    return;
}

// Función para actualizar los textos en la composición
function updateTextsInComp(comp, nom, xarxes) {
    for (var i = 1; i <= comp.numLayers; i++) {
        var layer = comp.layer(i);
        if (layer.property("Source Text") != null) {
            if (layer.name === "Nom") {
                layer.property("Source Text").setValue(nom);
                $.writeln("Texto de Nom actualizado a: " + nom);
            } else if (layer.name === "Xarxes") {
                layer.property("Source Text").setValue(xarxes);
                $.writeln("Texto de Xarxes actualizado a: " + xarxes);
            }
        }
    }
}

// Función para renderizar la composición
function renderComp(comp) {
    app.project.renderQueue.items.removeAll(); // Limpiar la cola de renderizado
    var renderQueueItem = app.project.renderQueue.items.add(comp); // Añadir la composición a la cola
    var outputModule = renderQueueItem.outputModule(1); // Obtener el primer módulo de salida

    // Configurar el archivo de salida
    var outputFilePath = new File(renderFolderPath + "/" + "CHY_DER_" + nom + "_" + xarxes + ".mov");
    outputModule.file = outputFilePath;

    // Comienza el renderizado
    app.project.renderQueue.render();
}

// Función principal
function main() {
    app.open(new File(projectFilePath)); // Abrir el proyecto

    var comp = null;
    for (var i = 1; i <= app.project.numItems; i++) {
        if (app.project.item(i).name === "CHY_DER_Persona") {
            comp = app.project.item(i); // Encontrar la composición
            break;
        }
    }

    if (comp == null) {
        alert("Composición CHY_DER_Persona no encontrada");
        return;
    }

    updateTextsInComp(comp, nom, xarxes); // Actualizar textos
    renderComp(comp); // Renderizar la composición
}

main();

 

 

This is the error that appears when I try to render in titular.html.

 

 

Thank you very much

 

Legend
September 29, 2024

Simply save your project at the end using:

// Save
app.executeCommand(5)

 

// Crear un archivo JSX temporal con los datos para reemplazar textos
const jsxScript = `
var projectFilePath = "${projectFilePath.replace(/\\/g, " / ")}"
var renderFolderPath = "${renderFolderPath.replace(/\\/g, " / ")}"
var nom = "${nom}"
var xarxes = "${xarxes}"
function updateTextsInComp(comp, nom, xarxes) {
  var nomFound = false
  var xarxesFound = false

  for (var i = 1; i <= comp.numLayers; i++) {
    var layer = comp.layer(i)
    if (layer.property("Source Text") != null) {
      if (layer.name === "Nom") {
        layer.property("Source Text").setValue(nom)
        $.writeln("Texto de Nom actualizado a: " + nom)
        nomFound = true
      } else if (layer.name === "Xarxes") {
        layer.property("Source Text").setValue(xarxes)
        $.writeln("Texto de Xarxes actualizado a: " + xarxes)
        xarxesFound = true
      }
    }
  }

  if (!nomFound) {
    $.writeln("No se encontró la capa 'Nom'.")
  }
  if (!xarxesFound) {
    $.writeln("No se encontró la capa 'Xarxes'.")
  }
}

function renderComp(comp) {
  var renderQueue = app.project.renderQueue
  while (renderQueue.numItems > 0) {
    renderQueue.item(1).remove()
  } // Limpiar cola de renderizado
  var renderQueueItem = app.project.renderQueue.items.add(comp) // Añadir la composición a la cola
  var outputModule = renderQueueItem.outputModule(1) // Obtener el primer módulo de salida

  var outputFilePath = new File(
    renderFolderPath + "/" + "CHY_DER_" + nom + "_" + xarxes + ".mov",
  )
  outputModule.file = outputFilePath // Configurar la ruta de salida

  $.writeln("Archivo de salida configurado en: " + outputFilePath.fsName) // Mensaje de depuración
  app.project.renderQueue.render() // Comienza el renderizado
}

function main() {
  app.open(new File(projectFilePath)) // Abrir el proyecto
  $.writeln("Proyecto abierto: " + projectFilePath)

  var comp = null
  for (var i = 1; i <= app.project.numItems; i++) {
    if (app.project.item(i).name === "CHY_DER_Persona") {
      comp = app.project.item(i) // Encontrar la composición
      break
    }
  }

  if (comp == null) {
    $.writeln("Error: Composición CHY_DER_Persona no encontrada.")
    alert("Composición CHY_DER_Persona no encontrada")
    return
  }

  updateTextsInComp(comp, nom, xarxes) // Actualizar textos
  renderComp(comp) // Renderizar la composición
}

main()
// Save
app.executeCommand(5)
        `

 

 

Participant
September 29, 2024

Yes, it works, but I still have a problem. When a render finishes, the save or don't save dialog box appears, which prevents me from sending different texts to render again until I click one of the two buttons. I wonder if there’s any way to disable that dialog box.
Thank you very much for your help.

 

Legend
September 29, 2024

I would use afterfx.exe instead of aerender.exe

 

server.js:

 

const http = require('http');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.url === '/render') {
        let body = '';
        req.on('data', chunk => {
            body += chunk.toString(); // Convertir Buffer a string
        });
        req.on('end', () => {
            try {
                const { nom, xarxes } = JSON.parse(body);
                console.log(`Renderizando con Nom: ${nom} y Xarxes: ${xarxes}`);

                // Ruta del archivo del proyecto After Effects
                const projectFilePath = "F:/OBS/Chyrons/Chyrons.aep";

                // Ruta donde se guardará el archivo renderizado
                const renderFolderPath = "F:/OBS/Chyrons/Render";
                
                // Crear nombre de archivo de salida
                const outputFileName = `CHY_DER_${nom}_${xarxes}.mov`;
                const outputFilePath = `${renderFolderPath}/${outputFileName}`;

                // Crear un archivo JSX temporal con los datos para reemplazar textos
                const jsxScript = `
                    var projectFilePath = "${projectFilePath.replace(/\\/g, "/")}";
                    var renderFolderPath = "${renderFolderPath.replace(/\\/g, "/")}";
                    var nom = "${nom}";
                    var xarxes = "${xarxes}";
                    function updateTextsInComp(comp, nom, xarxes) {
                        var nomFound = false;
                        var xarxesFound = false;

                        for (var i = 1; i <= comp.numLayers; i++) {
                            var layer = comp.layer(i);
                            if (layer.property("Source Text") != null) {
                                if (layer.name === "Nom") {
                                    layer.property("Source Text").setValue(nom);
                                    $.writeln("Texto de Nom actualizado a: " + nom);
                                    nomFound = true;
                                } else if (layer.name === "Xarxes") {
                                    layer.property("Source Text").setValue(xarxes);
                                    $.writeln("Texto de Xarxes actualizado a: " + xarxes);
                                    xarxesFound = true;
                                }
                            }
                        }

                        if (!nomFound) {
                            $.writeln("No se encontró la capa 'Nom'.");
                        }
                        if (!xarxesFound) {
                            $.writeln("No se encontró la capa 'Xarxes'.");
                        }
                    }

                    function renderComp(comp) {
                        var renderQueue = app.project.renderQueue;
						while (renderQueue.numItems > 0) {renderQueue.item(1).remove()} // Limpiar cola de renderizado
                        var renderQueueItem = app.project.renderQueue.items.add(comp); // Añadir la composición a la cola
                        var outputModule = renderQueueItem.outputModule(1); // Obtener el primer módulo de salida
                        
                        var outputFilePath = new File(renderFolderPath + "/" + "CHY_DER_" + nom + "_" + xarxes + ".mov");
                        outputModule.file = outputFilePath; // Configurar la ruta de salida

                        $.writeln("Archivo de salida configurado en: " + outputFilePath.fsName); // Mensaje de depuración
                        app.project.renderQueue.render(); // Comienza el renderizado
                    }

                    function main() {
                        app.open(new File(projectFilePath)); // Abrir el proyecto
                        $.writeln("Proyecto abierto: " + projectFilePath);

                        var comp = null;
                        for (var i = 1; i <= app.project.numItems; i++) {
                            if (app.project.item(i).name === "CHY_DER_Persona") {
                                comp = app.project.item(i); // Encontrar la composición
                                break;
                            }
                        }

                        if (comp == null) {
                            $.writeln("Error: Composición CHY_DER_Persona no encontrada.");
                            alert("Composición CHY_DER_Persona no encontrada");
                            return;
                        }

                        updateTextsInComp(comp, nom, xarxes); // Actualizar textos
                        renderComp(comp); // Renderizar la composición
                    }

                    main();
                `;

                // Guardar el archivo JSX temporalmente
                const jsxFilePath = path.join(__dirname, 'temp_render_script.jsx');
                fs.writeFileSync(jsxFilePath, jsxScript);

                // Comando para aerender
                const pathToAfterfx = `"C:\\Program Files\\Adobe\\Adobe After Effects 2023\\Support Files\\afterfx.exe"`;

                // Ejecutar aerender con el proyecto, la composición y la salida
                exec(`${pathToAfterfx} -s $.evalFile("${jsxFilePath.replace(/\\/g, "/")}")`, (error, stdout, stderr) => {
                    if (error) {
                        console.error(`Error al ejecutar aerender: ${error.message}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error al renderizar: ${error.message}`);
                        return;
                    }
                    if (stderr) {
                        console.error(`stderr: ${stderr}`);
                        res.writeHead(500, { 'Content-Type': 'text/plain' });
                        res.end(`Error en el script: ${stderr}`);
                        return;
                    }
                    console.log(`stdout: ${stdout}`);
                    res.writeHead(200, { 'Content-Type': 'text/plain' });
                    res.end('Renderizado iniciado');

                    // Limpiar el archivo JSX temporal
                    fs.unlinkSync(jsxFilePath);
                });

            } catch (e) {
                console.error(`Error al procesar JSON: ${e}`);
                res.writeHead(400, { 'Content-Type': 'text/plain' });
                res.end('Datos inválidos');
            }
        });
    } else {
        let filePath = path.join(__dirname, req.url === '/' ? 'index.html' : req.url);
        let extname = String(path.extname(filePath)).toLowerCase();
        let mimeTypes = {
            '.html': 'text/html',
            '.js': 'text/javascript',
            '.css': 'text/css',
            '.json': 'application/json',
        };

        let contentType = mimeTypes[extname] || 'application/octet-stream';

        fs.readFile(filePath, (error, content) => {
            if (error) {
                if (error.code == 'ENOENT') {
                    res.writeHead(404, { 'Content-Type': 'text/html' });
                    res.end('<h1>404 Not Found</h1>', 'utf-8');
                } else {
                    res.writeHead(500);
                    res.end('Sorry, there was an error: ' + error.code + '..\n');
                }
            } else {
                res.writeHead(200, { 'Content-Type': contentType });
                res.end(content, 'utf-8');
            }
        });
    }
});

const PORT = 8001;
server.listen(PORT, () => {
    console.log(`Servidor corriendo en http://localhost:${PORT}`);
});