Render a “clean frame,” as described, with no spotlights. Now, separately render only the spotlights. Use the spotlit images in the Fac input of a Mix node which takes information from the clean frame. Anywhere the spotlight falls, information will be used from the clean frame. (The spotlight data only serves to tell you where the spotlit area is.)
So, you have three things working here:
- The clean frame, darkened and desaturated to look like a foggy set.
- An appearance of volumetric light cones, however generated.
- Original data from the clean frame, superimposed where the light hits the stage.
If volumetrics are turning out to be expensive, you can render white cones that are parented to the lights and moving about under a sun lamp, the cones serving to tell you where the light-beams are. You then composite a suitable texture and take only the texture information. (You don’t need Cycles for this.)
“Almost anything can be ‘faked,’” if you are willing to put extra human-time into it and if you can also accept less-than-perfect results.
A key consideration is that we have made the “clean frame” exposure very easy. There’s plenty of light on “that stage which the audience never actually sees.” This means that the Cycles renderer can calculate a good solution quickly.
I would also very-strongly recommend that you look at Eevee. It continues to astound me.