You've said that you're interested in a baked solution, so here's what we can do given keyframes for the object whose axes we wish to track. I assume you already have an object with baked animation; I assume it's not experiencing any translation.
Let's start by making a single bone armature at the location of the tracked object. We'll enter pose mode on the armature, name our single bone "Current" and give it a copy rotation bone constraint targeting our tracked object; for simplicity, then select this bone and apply as rest pose (ctrl a menu in pose.) Then enter edit mode on the armature and duplicate this bone; we'll name this duplicate "minusOne" because it will eventually be tracking our object's rotation at a one frame offset. Play your animation; you'll find that your bones rotate with your object.
Now we can go back into pose mode on the armature. Use the "bake action" operation, and on it's interface, enable "visual keying" and "clear constraints". You'll see the constraints on your bone disappear and you'll have keyframes for your bones in their place; if you play the animation, you'll see the bones do the same thing they did with the constraints.
Now, in pose mode, select minusOne, and then select all keyframes in a timeline view, and move those 1 unit in the X axis in that timeline: 'g x 1 enter.' This means that minusOne now lags Current by one frame. Select Current and give it a "locked track" bone constraint, targeting its own armature but targeting minusOne in that armature. Set the constraint's track axis to -X, its locked axis to Y, and the head/tail to 1.0 to locked track the tail of minusOne:
Now put the armature into rest position in properties/object data/skeleton. Enter object mode, select the axis object, shift select armature, select Current, and ctrl p -> parent bone relative. Return your armature to pose position and play your animation. Your first frame shouldn't make any sense, but it's because you don't have any rotational velocity at frame 1; after that, you'll see that your pole remains perpendicular to the plane formed by Current and minusOne, which is the plane of rotation.
That's our axis of rotation taken care of, which was your primary concern. You're also interested in the direction of rotation. Your direction of rotation is always perpendicular to your axis, so you can parent any object you want to your axis and get the direction of rotation. If the rotation switches direction, the pole will "flip" and anything parented to it will as well. (If you don't want this to happen, it's possible with further constraints, but seeing as how this is going to be a long answer anyways, I'm not going to assume you need that.)
Your final request is to get the amount of velocity represented in the direction. That's possible too. There are a huge number of ways to get it. Let's do it with a mesh object with a few modifiers.
First, we need one more bone. In edit mode, duplicate minusOne, delete its animation, parent it to minusOne, and give it a constraint targeting Current. Give it a locked track constraint, locked Y track +X, at head/tail 1.0. Name this "minusOneChild".
Next, we'll make a weird mesh object. We'll call this object "Skinned". Make a plane, then in edit, delete two vertices. Scale both remaining vertices to zero so they occupy the exact same location at , but do not merge. Parent this plane to your armature with armature deform->empty groups. In edit mode, select one vertex and assign to minusOneChild vertex group at 1.0 weight; assign the other to Current at 1.0 weight. This plane now has an armature modifier due to the parenting; follow this modifier with a skin modifier to turn the line formed into an actual mesh.
This creates a straight line, but we want a circle to describe the direction and velocity of motion. We can do that procedurally, which is something I like. Give Skinned a subdivision modifier, with a few extra iterations, and move it to the top of the modifier stack, above the armature modifier. Then enable "preserve volume" on your armature modifier. The subdivision will interpolate weights between the two vertices automatically, and the armature will now use quaternions to calculate the mix between two bones, giving us an arc of a perfect circle:
The only problem remaining is that it's a little short. We're looking at the difference in rotation between a frame and the one immediately previous, which is small, so the rotational velocity we're showing is small as well. We might want to exaggerate that some, while keeping it proportional to the actual relative velocity (so multiplying it by something, rather than adding it to something.)
Again, there are many different ways to do that. I'll do it with a pair of bones and bone constraints.
Enter edit on your armature. Duplicate minusOneChild twice and parent both copies to Current. Name the first "measureRotation". Name the second "multiplyRotation." Give measureRotation a locked track constraint targeting minusOne, set to lock Z, track +Y, head/tail 1.0. Then give multiplyRotation a transformation constraint targeting measureRotation. Set it to work in local->local, to map rotation to rotation, with extrapolate enabled, and to map -1,1 degrees Z rotation to -10,10 degrees Z rotation-- so we're showing an arc ten times bigger than what we had to begin with.
Select Skinned, and in properties/object data/vertex groups, rename minusOne to multiplyRotation to weight from this new bone. Finally, if we'd like, we can create a cone or something and bone parent it to Current.
Note, of course, that nothing is defined when the object has no rotational velocity! At that point, we're basically dividing by zero. (And remember, at frame 1, it has no rotational velocity yet.) Recommended would be to create a driver that hides your objects when the the local rotation of measureRotation is 0. Again, as something optional in an answer that is already overly long, if you need help with that, I'll leave it for a different question.