If you store the topics/payloads (or whatever you need) inside objects in an array, you can add a timestamp. Then when you playback the array, you can adjust the timestamps of all items by the difference of now minus the timestamp of the 1st message.
Then you can send that array to node-red-contrib-cron-plus
and it will dynamically add these as scheduled entries and send the values at the specified time.
demo...
demo flow ...
[{"id":"3852ef38911058af","type":"cronplus","z":"a4633311d1bf470d","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output2","outputs":2,"options":[],"x":1680,"y":480,"wires":[["4af4fd6aeb97ff22","8fb5483e3cf5e486"],[]]},{"id":"c1499213e51ec5fc","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 1","payload":"payload 1","payloadType":"str","x":1440,"y":140,"wires":[["5df070b0c3b59100"]]},{"id":"2736245fa940ceaf","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 1","payload":"payload 2","payloadType":"str","x":1440,"y":180,"wires":[["5df070b0c3b59100"]]},{"id":"44fc61ea423c0de7","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"payload 1","payloadType":"str","x":1440,"y":240,"wires":[["5df070b0c3b59100"]]},{"id":"2fa09290425699a7","type":"inject","z":"a4633311d1bf470d","name":"topic 2: 2 (number payload)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"2","payloadType":"num","x":1410,"y":280,"wires":[["5df070b0c3b59100"]]},{"id":"5df070b0c3b59100","type":"function","z":"a4633311d1bf470d","name":"message recorder","func":"let message_store = flow.get(\"message_store\") || [];\n\nif(msg.topic == \"CLEAR-STORE\") {\n message_store = [];\n} else {\n const clone = {\n timestamp: Date.now(),\n topic: msg.topic,\n payload: RED.util.cloneMessage(msg.payload),\n };\n message_store.push(clone);\n}\n\nflow.set(\"message_store\", message_store);\n\nmsg.payload = message_store;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1690,"y":220,"wires":[["c89ba12007b13be6"]]},{"id":"9073e6e9a25a3da0","type":"inject","z":"a4633311d1bf470d","name":"playback","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1460,"y":400,"wires":[["2e2bdc612970a754"]]},{"id":"2e2bdc612970a754","type":"function","z":"a4633311d1bf470d","name":"prepare playback","func":"const message_store = flow.get(\"message_store\") || [];\n// debugger\nif(message_store.length == 0) {\n node.warn(\"flow.message_store has no data\");\n return null;\n}\nconst now = Date.now();\nconst ts = message_store[0].timestamp\nconst diff = now - ts;\nconst start_offset_ms = 200;\n\nif(diff < 0) {\n node.warn(\"flow.message_store data is invalid\");\n return null;\n}\n\nconst schedules = message_store.map((e, i) => {\n let ptype = \"default\";\n switch (typeof e.payload) {\n case \"string\":\n ptype = \"str\";\n break;\n case \"boolean\":\n ptype = \"bool\";\n break;\n case \"object\":\n ptype = \"json\";\n break;\n case \"number\":\n ptype = \"num\";\n break;\n default:\n }\n return {\n \"command\": \"add\",\n \"name\": \"schedule\" + (i+1),\n \"expression\": e.timestamp + diff + start_offset_ms,\n \"expressionType\": \"dates\",\n \"payloadType\": ptype,\n \"payload\": e.payload,\n \"topic\": e.topic\n }\n})\n\nschedules.unshift({ \"command\": \"remove-all-dynamic\" });\n\nmsg.topic = \"\";\nmsg.payload = schedules;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1710,"y":400,"wires":[["3852ef38911058af","256c50f56a0f3eb5"]]},{"id":"4af4fd6aeb97ff22","type":"debug","z":"a4633311d1bf470d","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"topic","targetType":"msg","statusVal":"payload","statusType":"auto","x":1960,"y":420,"wires":[]},{"id":"8fb5483e3cf5e486","type":"debug","z":"a4633311d1bf470d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1970,"y":480,"wires":[]},{"id":"e0b94a823c96e466","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"CLEAR-STORE","x":1440,"y":80,"wires":[["5df070b0c3b59100"]]},{"id":"256c50f56a0f3eb5","type":"debug","z":"a4633311d1bf470d","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1970,"y":340,"wires":[]},{"id":"19d6e675cf1cd4fd","type":"inject","z":"a4633311d1bf470d","name":"topic 2: { object payload }","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"{\"prop\": \"i am a prop in a JS object\"}","payloadType":"json","x":1410,"y":320,"wires":[["5df070b0c3b59100"]]},{"id":"c89ba12007b13be6","type":"debug","z":"a4633311d1bf470d","name":"store count","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"\"Store count: \" & $count(msg.payload)","statusType":"jsonata","x":1910,"y":220,"wires":[]}]