Skip to content

Instantly share code, notes, and snippets.

@gssariev
Last active January 10, 2025 16:07
Show Gist options
  • Save gssariev/0b93a11e809c38e035388e4157b42c9a to your computer and use it in GitHub Desktop.
Save gssariev/0b93a11e809c38e035388e4157b42c9a to your computer and use it in GitHub Desktop.
Henk's plugin v3 - handling undefined audio tracks. All undefined audio tracks will be tagged with either a user-specified tag or with the original language tag (if no user tags have been specified)
/* eslint-disable no-await-in-loop */
module.exports.dependencies = ['[email protected]', '@cospired/i18n-iso-languages'];
const details = () => ({
id: 'Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng',
Stage: 'Pre-processing',
Name: 'Remove all langs except native and English',
Type: 'Audio',
Operation: 'Transcode',
Description: `This is a modified version made by gsariev of the original plugin. This plugin will remove all language audio tracks except the 'native' and user-specified languages.
(requires TMDB api key).
'Native' languages are the ones that are listed on TMDB. It does an API call to
Radarr, Sonarr to check if the movie/series exists and grabs the IMDb id. As a last resort, it
falls back to the IMDb id in the filename.`,
Version: '1.3', // Incremented version
Tags: 'pre-processing,configurable',
Inputs: [
{
name: 'user_langs',
type: 'string',
defaultValue: '',
inputUI: {
type: 'text',
},
tooltip:
'Input a comma-separated list of ISO-639-2 languages. It will still keep English and undefined tracks.'
+ '(https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes 639-2 column)'
+ '\\nExample:\\n'
+ 'ger,fre',
},
{
name: 'priority',
type: 'string',
defaultValue: 'radarr',
inputUI: {
type: 'text',
},
tooltip:
'Priority for either Radarr or Sonarr. Leaving it empty defaults to Radarr first.'
+ '\\nExample:\\n'
+ 'sonarr',
},
{
name: 'api_key',
type: 'string',
defaultValue: '',
inputUI: {
type: 'text',
},
tooltip:
'Input your TMDB api (v3) key here. (https://www.themoviedb.org/)',
},
{
name: 'radarr_api_key',
type: 'string',
defaultValue: '',
inputUI: {
type: 'text',
},
tooltip: 'Input your Radarr api key here.',
},
{
name: 'radarr_url',
type: 'string',
defaultValue: '192.168.1.2:7878',
inputUI: {
type: 'text',
},
tooltip:
'Input your Radarr url here. (Without http://). Do include the port.'
+ '\\nExample:\\n'
+ '192.168.1.2:7878',
},
{
name: 'sonarr_api_key',
type: 'string',
defaultValue: '',
inputUI: {
type: 'text',
},
tooltip: 'Input your Sonarr api key here.',
},
{
name: 'sonarr_url',
type: 'string',
defaultValue: '192.168.1.2:8989',
inputUI: {
type: 'text',
},
tooltip:
'Input your Sonarr url here. (Without http://). Do include the port.'
+ '\\nExample:\\n'
+ '192.168.1.2:8989',
},
{
name: 'commentary',
type: 'boolean',
defaultValue: false,
inputUI: {
type: 'dropdown',
options: [
'false',
'true',
],
},
tooltip: `Specify if audio tracks that contain commentary/description should be kept.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'undefined_lang_tag',
type: 'string',
defaultValue: '',
inputUI: {
type: 'text',
},
tooltip:
'Specify the language tag to use for undefined audio tracks. If empty, the original language tag will be used.',
},
],
});
const response = {
processFile: false,
preset: '',
container: '.',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
};
const languageConverter = (tmdbLanguageCode) => {
const isoLang = require('@cospired/i18n-iso-languages');
try {
// Convert TMDB language code to ISO-639-2 3-letter format
const convertedLanguageCode = isoLang.alpha2ToAlpha3B(tmdbLanguageCode);
// Log the converted language code
response.infoLog += `TMDB Language Code Return: ${convertedLanguageCode}\n`;
return convertedLanguageCode;
} catch (error) {
console.error('Error converting language code:', error.message);
response.infoLog += '☒Error converting language code.\n';
return null;
}
};
const parseArrResponse = (body, filePath, arr) => {
// eslint-disable-next-line default-case
switch (arr) {
case 'radarr':
return body.movie;
case 'sonarr':
return body.series;
}
};
const processStreams = (result, file, userLangs, isSonarr, includeCommentary, undefinedLangTag) => {
const languages = require('@cospired/i18n-iso-languages');
const tracks = {
keep: [],
remove: [],
remLangs: '',
metadata: '',
};
let streamIndex = 0;
let shouldProcess = false;
// Convert the TMDB language code to ISO-639-2 3-letter format dynamically
const tmdbLanguageCode = result.original_language;
const convertedLanguageCode = languageConverter(tmdbLanguageCode) || tmdbLanguageCode;
response.infoLog += `Original language tag: ${convertedLanguageCode}\n`;
// Flag to indicate if any audio track matches the specified languages
let matchFound = false;
for (const stream of file.ffProbeData.streams) {
if (stream.codec_type === 'audio') {
if (!stream.tags || !stream.tags.language || stream.tags.language.toLowerCase() === 'und') {
// Explicitly identify undefined tracks
const tagLanguage = undefinedLangTag || convertedLanguageCode;
response.infoLog += `☒No language tag found on audio track ${streamIndex}. Tagging it with ${tagLanguage}.\n`;
// Tag the undefined audio track
tracks.metadata += `-metadata:s:a:${streamIndex} language=${tagLanguage} `;
tracks.keep.push(streamIndex);
response.infoLog += `☑Tagged audio track ${streamIndex} with ${tagLanguage}\n`;
matchFound = true; // Consider this a match since we are tagging it appropriately
shouldProcess = true; // Mark the file to be processed
} else if (stream.tags.title && isCommentaryTrack(stream.tags.title)) {
// Remove commentary tracks if includeCommentary is false
if (!includeCommentary) {
response.infoLog += `☒Removing commentary audio track: ${languages.getName(stream.tags.language, 'en')} (commentary) - ${stream.tags.title}\n`;
tracks.remove.push(streamIndex);
tracks.remLangs += `${languages.getName(stream.tags.language, 'en')} (commentary), `;
shouldProcess = true; // Mark the file to be processed
} else {
tracks.keep.push(streamIndex);
response.infoLog += `☑Keeping commentary audio track: ${languages.getName(stream.tags.language, 'en')} (commentary) - ${stream.tags.title}\n`;
matchFound = true; // At least one track matches the specified languages
}
} else if (stream.tags.language) {
// Check if the language is in the user-defined languages or it's the original language
const mappedLanguage = isSonarr ? mapSonarrLanguageToTMDB(stream.tags.language) : mapRadarrLanguageToTMDB(stream.tags.language);
if (userLangs.includes(mappedLanguage) || mappedLanguage === convertedLanguageCode) {
tracks.keep.push(streamIndex);
response.infoLog += `☑Keeping audio track with language: ${languages.getName(stream.tags.language, 'en')}\n`;
matchFound = true; // At least one track matches the specified languages
} else {
response.infoLog += `☒Removing audio track with language: ${languages.getName(stream.tags.language, 'en')}\n`;
tracks.remove.push(streamIndex);
tracks.remLangs += `${languages.getName(stream.tags.language, 'en')}, `;
shouldProcess = true; // Mark the file to be processed
}
}
streamIndex += 1;
}
}
// If no tracks are found to match the specified languages and none are kept, stop the plugin
if (!matchFound && tracks.keep.length === 0) {
response.infoLog += '☒Cancelling plugin because none of the audio tracks match the specified languages or are tagged as undefined. \n';
response.processFile = false;
// Clear the removal tracks to prevent further deletion
tracks.remove = [];
} else {
response.processFile = shouldProcess; // Process the file if at least one track is kept or tagged
}
if (shouldProcess) {
response.preset = `, -map 0:v -c:v copy `;
for (const index of tracks.keep) {
response.preset += `-map 0:a:${index} `;
}
for (const index of tracks.remove) {
response.preset += `-map -0:a:${index} `;
}
response.preset += `${tracks.metadata} -c:a copy -max_muxing_queue_size 9999`;
}
return tracks;
};
const mapRadarrLanguageToTMDB = (radarrLanguage) => {
const languageMappings = {
chi: 'cn',
// Add additional mapping if needed
};
return languageMappings[radarrLanguage] || radarrLanguage;
};
const mapSonarrLanguageToTMDB = (sonarrLanguage) => {
const languageMappings = {
// Add mappings for Sonarr languages if needed
};
return languageMappings[sonarrLanguage] || sonarrLanguage;
};
const tmdbApi = async (filename, api_key, axios) => {
let fileName;
if (filename) {
if (filename.slice(0, 2) === 'tt') {
fileName = filename;
} else {
const idRegex = /(tt\d{7,8})/;
const fileMatch = filename.match(idRegex);
if (fileMatch) {
fileName = fileMatch[1];
}
}
}
if (fileName) {
try {
const result = await axios
.get(
`https://api.themoviedb.org/3/find/${fileName}?api_key=`
+ `${api_key}&language=en-US&external_source=imdb_id`,
)
.then((resp) => (resp.data.movie_results.length > 0
? resp.data.movie_results[0]
: resp.data.tv_results[0]));
console.log('TMDB API Result:', result);
if (!result) {
response.infoLog += '☒No IMDb result was found. \n';
}
if (result) {
const tmdbLanguageCode = languageConverter(result.original_language);
response.infoLog += `Converted TMDB Language Code: ${tmdbLanguageCode}\n`;
response.infoLog += `Language tag picked up by TMDB: ${tmdbLanguageCode}\n`;
} else {
response.infoLog += "☒Couldn't find the IMDb id of this file. Skipping. \n";
}
return result;
} catch (error) {
console.error('Error fetching data from TMDB API:', error.message);
response.infoLog += '☒Error fetching data from TMDB API.\n';
return null;
}
}
return null;
};
const isCommentaryTrack = (title) => {
// Check if the title includes keywords indicating a commentary track
return title.toLowerCase().includes('commentary')
|| title.toLowerCase().includes('description')
|| title.toLowerCase().includes('sdh');
};
const plugin = async (file, librarySettings, inputs, otherArguments) => {
const lib = require('../methods/lib')();
const axios = require('axios').default;
inputs = lib.loadDefaultValues(inputs, details);
response.container = `.${file.container}`;
let prio = ['radarr', 'sonarr'];
let radarrResult = null;
let sonarrResult = null;
let tmdbResult = null;
if (inputs.priority && inputs.priority === 'sonarr') {
prio = ['sonarr', 'radarr'];
}
const fileNameEncoded = encodeURIComponent(file.meta.FileName);
for (const arr of prio) {
let imdbId;
// Reset infoLog before each processing step (removes duplicated logs being displayed)
response.infoLog = '';
switch (arr) {
case 'radarr':
if (tmdbResult) break;
if (inputs.radarr_api_key) {
radarrResult = parseArrResponse(
await axios
.get(
`http://${inputs.radarr_url}/api/v3/parse?apikey=${inputs.radarr_api_key}&title=${fileNameEncoded}`,
)
.then((resp) => resp.data),
fileNameEncoded,
'radarr',
);
if (radarrResult) {
imdbId = radarrResult.imdbId;
response.infoLog += `Grabbed ID (${imdbId}) from Radarr \n`;
const radarrLanguageTag = radarrResult.originalLanguage.name;
response.infoLog += `Language tag picked up by Radarr: ${radarrLanguageTag}\n`;
tmdbResult = await tmdbApi(imdbId, inputs.api_key, axios);
if (tmdbResult) {
const tmdbLanguageTag = languageConverter(tmdbResult.original_language) || tmdbResult.original_language;
response.infoLog += `Language tag picked up by TMDB: ${tmdbLanguageTag}\n`;
}
} else {
response.infoLog += "Couldn't grab ID from Radarr \n";
imdbId = fileNameEncoded;
tmdbResult = await tmdbApi(imdbId, inputs.api_key, axios);
if (tmdbResult) {
const tmdbLanguageTag = languageConverter(tmdbResult.original_language) || tmdbResult.original_language;
response.infoLog += `Language tag picked up by TMDB: ${tmdbLanguageTag}\n`;
}
}
}
break;
case 'sonarr':
if (tmdbResult) break;
if (inputs.sonarr_api_key) {
sonarrResult = parseArrResponse(
await axios.get(
`http://${inputs.sonarr_url}/api/v3/parse?apikey=${inputs.sonarr_api_key}&title=${fileNameEncoded}`,
)
.then((resp) => resp.data),
file.meta.Directory,
'sonarr',
);
if (sonarrResult) {
imdbId = sonarrResult.imdbId;
response.infoLog += `Grabbed ID (${imdbId}) from Sonarr \n`;
tmdbResult = await tmdbApi(imdbId, inputs.api_key, axios);
if (tmdbResult) {
const sonarrTracks = processStreams(tmdbResult, file, inputs.user_langs ? inputs.user_langs.split(',') : '', true, inputs.commentary, inputs.undefined_lang_tag);
if (sonarrTracks.remove.length > 0) {
if (sonarrTracks.keep.length > 0) {
response.infoLog += `☑Removing tracks with languages: ${sonarrTracks.remLangs.slice(
0,
-2,
)}. \n`;
response.processFile = true;
response.infoLog += '\n';
} else {
response.infoLog
+= '☒Cancelling plugin otherwise all audio tracks would be removed. \n';
}
} else {
response.infoLog += '☒No audio tracks to be removed. \n';
}
} else {
response.infoLog += "☒Couldn't find the IMDb id of this file. Skipping. \n";
}
}
}
break;
}
}
if (tmdbResult) {
const userLanguages = inputs.user_langs ? inputs.user_langs.split(',') : [];
const originalLanguage = tmdbResult.original_language;
const originalLanguageIncluded = userLanguages.includes(originalLanguage);
const tracks = processStreams(
tmdbResult,
file,
userLanguages,
false,
inputs.commentary,
inputs.undefined_lang_tag,
);
console.log('Tracks:', tracks);
console.log('Original Language:', originalLanguage);
console.log('User Languages:', userLanguages);
console.log('Original Language Included:', originalLanguageIncluded);
console.log('User Languages Include Removed Languages:', userLanguages.includes(tracks.remLangs));
// Check if no tracks match original or user-specified languages
const noMatchingTracks = tracks.keep.length === 0 && !originalLanguageIncluded && !userLanguages.includes(tracks.remLangs);
console.log('No Matching Tracks:', noMatchingTracks);
if (noMatchingTracks) {
response.infoLog += '☒Cancelling plugin because no audio tracks match the original language or user-specified languages. \n';
return response; // Stop execution
}
// Continue processing audio tracks
if (tracks.remove.length > 0) {
if (tracks.keep.length > 0) {
response.infoLog += `☑Removing tracks with languages: ${tracks.remLangs.slice(
0,
-2,
)}. \n`;
response.processFile = true;
response.infoLog += '\n';
} else {
response.infoLog += '☒Cancelling plugin otherwise all audio tracks would be removed. \n';
}
} else {
response.infoLog += '☒No audio tracks to be removed. \n';
}
} else {
response.infoLog += "☒Couldn't find the IMDb id of this file. Skipping. \n";
}
return response;
};
module.exports.details = details;
module.exports.plugin = plugin;
@gssariev
Copy link
Author

Fixed an issue that caused the commentary tracks to not be properly removed resulting in a loop/same arguments error.

@emulated24
Copy link

For some reason, the plugin removes all subtitles from the movie.
I'm using latest docker image of Tdarr.

This is what I found in the logs:
[matroska,webm @ 0x55eac5fccf80] Could not find codec parameters for stream 4 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size 2024-12-22T14:01:32.886Z Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options 2024-12-22T14:01:32.886Z [matroska,webm @ 0x55eac5fccf80] Could not find codec parameters for stream 5 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size

After that I see three streams copied over, the rest is ignored for some reason:
2024-12-22T14:01:32.886Z Stream mapping: 2024-12-22T14:01:32.886Z Stream #0:0 -> #0:0 (copy) 2024-12-22T14:01:32.886Z Stream #0:1 -> #0:1 (copy) 2024-12-22T14:01:32.886Z Stream #0:2 -> #0:2 (copy)

2024-12-22T14:01:32.886Z video:4814991kB audio:948259kB subtitle:0kB other streams:0kB global headers:3kB muxing overhead: 0.082985%

What could be the reason for this unexpected plugin behaviour please?

@gssariev
Copy link
Author

gssariev commented Jan 4, 2025

For some reason, the plugin removes all subtitles from the movie. I'm using latest docker image of Tdarr.

This is what I found in the logs: [matroska,webm @ 0x55eac5fccf80] Could not find codec parameters for stream 4 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size 2024-12-22T14:01:32.886Z Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options 2024-12-22T14:01:32.886Z [matroska,webm @ 0x55eac5fccf80] Could not find codec parameters for stream 5 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size

After that I see three streams copied over, the rest is ignored for some reason: 2024-12-22T14:01:32.886Z Stream mapping: 2024-12-22T14:01:32.886Z Stream #0:0 -> #0:0 (copy) 2024-12-22T14:01:32.886Z Stream #0:1 -> #0:1 (copy) 2024-12-22T14:01:32.886Z Stream #0:2 -> #0:2 (copy)

2024-12-22T14:01:32.886Z video:4814991kB audio:948259kB subtitle:0kB other streams:0kB global headers:3kB muxing overhead: 0.082985%

What could be the reason for this unexpected plugin behaviour please?

I am sorry for the late reply (holidays).

It's been a while since I've worked on this plugin, but will try to help as best as I can. For starters, the plugin doesn't handle subtitles - only audio tracks - and I haven't ran into the issue you are describing.

Would you mind sharing your plugin stack and full Tdarr logs? Perhaps I can try and replicate things on my end.

@emulated24
Copy link

No worries, fully understand. :)

Yes, that is exactly what I thought. The plugin should leave all subtitle tracks intact. But for some reason, it doesn't and it removes them all.

Here's my flow:
{ "_id": "tCvLGQPX-", "name": "Test", "description": "Test", "tags": "", "flowPlugins": [ { "name": "Input File", "sourceRepo": "Community", "pluginName": "inputFile", "version": "1.0.0", "id": "gtZCtmY-l", "position": { "x": 648.6536861377089, "y": -82.45578042880155 }, "fpEnabled": true, "inputsDB": { "fileAccessChecks": "true" } }, { "name": "CheckHEVC", "sourceRepo": "Community", "pluginName": "checkVideoCodec", "version": "1.0.0", "id": "PpLF-5jxp", "position": { "x": 752.4065242952165, "y": 51.12406033129332 }, "fpEnabled": true }, { "name": "Replace Original File", "sourceRepo": "Community", "pluginName": "replaceOriginalFile", "version": "1.0.0", "id": "R0gX9B20d", "position": { "x": 1254.8245927603703, "y": 794.237280211442 }, "fpEnabled": true }, { "name": "KeepNativeEngCzeSlo", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "2.0.0", "id": "eoWKnzTXP", "position": { "x": 1253.4279202634789, "y": 434.8292360884601 }, "fpEnabled": true, "inputsDB": { "pluginSourceId": "Local:Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng", "commentary": "false", "user_langs": "eng,en,ces,cze,cz,slk,slo,sk", "api_key": "<redacted>", "radarr_api_key": "<redacted>", "radarr_url": "<redacted>", "sonarr_api_key": "<redacted>", "sonarr_url": "<redacted>" } }, { "name": "MigzImageRemoval", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "2.0.0", "id": "chjsrPKGR", "position": { "x": 1249.6530739220775, "y": 256.2746302482324 }, "fpEnabled": true, "inputsDB": { "pluginSourceId": "Community:Tdarr_Plugin_MC93_MigzImageRemoval" } }, { "name": "CheckH264", "sourceRepo": "Community", "pluginName": "checkVideoCodec", "version": "1.0.0", "id": "STdtYX6Uz", "position": { "x": 1230.3802603124673, "y": 64.9759069468966 }, "fpEnabled": true, "inputsDB": { "codec": "h264" } }, { "name": "ReorderStreams", "sourceRepo": "Community", "pluginName": "ffmpegCommandRorderStreams", "version": "1.0.0", "id": "zCPoUm97Y", "position": { "x": 1250.3866346826792, "y": 368.4893797537838 }, "fpEnabled": true }, { "name": "CleanSubs", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "2.0.0", "id": "nikQ2_m-M", "position": { "x": 1254.2140730609997, "y": 534.3905146082651 }, "fpEnabled": true, "inputsDB": { "pluginSourceId": "Community:Tdarr_Plugin_MC93_Migz4CleanSubs", "language": "eng,en,ces,cze,cz,slk,slo,sk" } }, { "name": "ReviewFilesize", "sourceRepo": "Community", "pluginName": "requireReview", "version": "1.0.0", "id": "huCCai3iZ", "position": { "x": 1453.365281594849, "y": 706.8664811983667 }, "fpEnabled": true }, { "name": "FilesizeRatio", "sourceRepo": "Community", "pluginName": "compareFileSizeRatio", "version": "2.0.0", "id": "fuaM-8QAs", "position": { "x": 1250.8288506657948, "y": 632.5022823009829 }, "fpEnabled": true, "inputsDB": { "lessThan": "105", "greaterThan": "70" } }, { "name": "ReviewCodec", "sourceRepo": "Community", "pluginName": "requireReview", "version": "1.0.0", "id": "DTFMwFD7e", "position": { "x": 1496.347248161808, "y": 142.39819281918466 }, "fpEnabled": true }, { "name": "Fail Flow", "sourceRepo": "Community", "pluginName": "failFlow", "version": "1.0.0", "id": "qKljJUfOC", "position": { "x": 1494.4249247324803, "y": 222.10190965590937 }, "fpEnabled": true }, { "name": "CheckAV1", "sourceRepo": "Community", "pluginName": "checkVideoCodec", "version": "1.0.0", "id": "aChUlx9if", "position": { "x": 1044.9791563079516, "y": 10.429252272318273 }, "fpEnabled": true, "inputsDB": { "codec": "av1" } }, { "name": "FFmpegBegin", "sourceRepo": "Community", "pluginName": "ffmpegCommandStart", "version": "1.0.0", "id": "NjpCAx2Ew", "position": { "x": 1526.7571611839783, "y": 297.1714054699728 }, "fpEnabled": true }, { "name": "FFmpegExecute", "sourceRepo": "Community", "pluginName": "ffmpegCommandExecute", "version": "1.0.0", "id": "ZhoIqK0Ao", "position": { "x": 1527.7571611839783, "y": 379.1714054699728 }, "fpEnabled": true } ], "flowEdges": [ { "source": "gtZCtmY-l", "sourceHandle": "1", "target": "PpLF-5jxp", "targetHandle": null, "id": "Cs5aBSUks" }, { "source": "fuaM-8QAs", "sourceHandle": "2", "target": "huCCai3iZ", "targetHandle": null, "id": "dE-DQNh1v" }, { "source": "fuaM-8QAs", "sourceHandle": "3", "target": "huCCai3iZ", "targetHandle": null, "id": "C6HFJyXla" }, { "source": "zCPoUm97Y", "sourceHandle": "1", "target": "eoWKnzTXP", "targetHandle": null, "id": "CtDyrUveh" }, { "source": "PpLF-5jxp", "sourceHandle": "1", "target": "chjsrPKGR", "targetHandle": null, "id": "uqzH-nvFB" }, { "source": "STdtYX6Uz", "sourceHandle": "1", "target": "chjsrPKGR", "targetHandle": null, "id": "OxAfx4gGH" }, { "source": "eoWKnzTXP", "sourceHandle": "1", "target": "nikQ2_m-M", "targetHandle": null, "id": "7t1vl9UOW" }, { "source": "nikQ2_m-M", "sourceHandle": "1", "target": "fuaM-8QAs", "targetHandle": null, "id": "a01Zri_ke" }, { "source": "STdtYX6Uz", "sourceHandle": "2", "target": "DTFMwFD7e", "targetHandle": null, "id": "pVL95VQ33" }, { "source": "huCCai3iZ", "sourceHandle": "1", "target": "R0gX9B20d", "targetHandle": null, "id": "XjMmZ5oBP" }, { "source": "DTFMwFD7e", "sourceHandle": "1", "target": "qKljJUfOC", "targetHandle": null, "id": "IW4yUuOFs" }, { "source": "PpLF-5jxp", "sourceHandle": "2", "target": "aChUlx9if", "targetHandle": null, "id": "yKqv0rTnu" }, { "source": "aChUlx9if", "sourceHandle": "1", "target": "chjsrPKGR", "targetHandle": null, "id": "iNLT0jTeF" }, { "source": "aChUlx9if", "sourceHandle": "2", "target": "STdtYX6Uz", "targetHandle": null, "id": "ygzMMi1dS" }, { "source": "chjsrPKGR", "sourceHandle": "1", "target": "NjpCAx2Ew", "targetHandle": null, "id": "G27skorfw" }, { "source": "chjsrPKGR", "sourceHandle": "2", "target": "NjpCAx2Ew", "targetHandle": null, "id": "H7M_fqU9x" }, { "source": "NjpCAx2Ew", "sourceHandle": "1", "target": "ZhoIqK0Ao", "targetHandle": null, "id": "ZtZCtLUxW" }, { "source": "ZhoIqK0Ao", "sourceHandle": "1", "target": "zCPoUm97Y", "targetHandle": null, "id": "UjnxDGAG1" }, { "source": "eoWKnzTXP", "sourceHandle": "2", "target": "nikQ2_m-M", "targetHandle": null, "id": "detlnS7_u" }, { "source": "nikQ2_m-M", "sourceHandle": "2", "target": "fuaM-8QAs", "targetHandle": null, "id": "Dw9AVmb07" }, { "source": "fuaM-8QAs", "sourceHandle": "1", "target": "R0gX9B20d", "targetHandle": null, "id": "dcpor_IGL" } ] }

Full logfile is attached, please rename to .txt
hfxc_Kzckg-log txt

@emulated24
Copy link

Not sure if the logfile is uploaded correctly. Shared online: https://file.io/hStDXZjUWI7v

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment