Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difference between on_play and on_publish #1730

Open
narayanan-ka opened this issue Jun 23, 2023 · 3 comments
Open

Difference between on_play and on_publish #1730

narayanan-ka opened this issue Jun 23, 2023 · 3 comments

Comments

@narayanan-ka
Copy link

narayanan-ka commented Jun 23, 2023

I can't understand the difference between on_play and on_publish. Can @arut please explain to me in simple terms ?Your response would be helpful. I can't understand which one to use.

My use case is : Have a django api server for authentication and I intend to use the nginx rtmp module for live streaming and video on demand. For live, i'm currently using the on_publish and on_publish_done which point to 2 functions on my django end to invoke a start a stream and stop a stream. However, For VOD, however, I need to allow the user to upload the file first to nginx after clicking upload and then nginx handles the processing and playing. Can I use the same 2 on_publish and on_publish_done to accept an upload from django end inside the rtmp block.

I have something like this :

    application vod {
        # Live status
        live off;

        # disable consuming the stream from nginx as rtmp
        deny play all;

        # Push the video stream to the local vod application for playing flv's
        push rtmp://www.mydomain.come:4935/vod-flv/;

        # Make HTTP request & use HTTP retcode
        # to decide whether to allow publishing
        # from this connection or not
        # The on_publish callback will redirect the RTMP stream to the streamer's username, rather than their secret stream key
        on_publish      http://www.mydomain.come:80/my-api/vod/startstream/;

        on_publish_dcome http://www.mydomain.come:80/my-api/vod/stopstream/;
    }

    application vod-flv {
        live off;
        # Only accept publishing from localhost.
        # (the `app` RTMP ingest application)
        allow publish www.mydomain.come;

        # play /opt/data/vod-flv/;
        flv_path  /opt/data/vod-flv/;

        allow publish all;

        allow play all;

        Use FLV encryption
        flv_keys on;
        flv_key_path /opt/data/keys/flv;
        flv_fragments_per_key 6;
        flv_key_url /keys/flv/;
    }
@lovgrandma
Copy link

lovgrandma commented Jun 28, 2023

With on_publish you can forward the on publish request to a server. I use it to allow users to use the same streamkey but redirect to another application with the name set to the actual uuid of the individual stream I want to begin.

That is my workflow. on_play I havent used. Maybe someone else has a better explanation.

See my example go server:

func main() {
       go serverStreamingServer()
}

func serveStreamingServer() *http.Server {
	http.HandleFunc("/stream/publish", handleIngestLiveStreamPublishAuthentication)
	log.Printf("Media Compliant Server listening at %v", streamingServicesPort)
	err := http.ListenAndServe(serviceAddress+streamingServicesPort, nil)
	if err != nil {
		log.Fatalf("Failed to run Media Compliant Server: %v", err)
	}
	return &http.Server{}
}
func handleIngestLiveStreamPublishAuthentication(w http.ResponseWriter, r *http.Request) {
	log.Println("Received Publish request at /stream/publish")
	body, err := io.ReadAll(r.Body)
	if err != nil {
		// Handle error
		log.Println("Error reading request body:", err)
		http.Error(w, "Error reading request body", http.StatusInternalServerError)
		return
	}

	query, err := url.ParseQuery(string(body))
	if err != nil {
		log.Println("Error parsing query string:", err)
		http.Error(w, "Error parsing query string", http.StatusInternalServerError)
		return
	}

	// Get the value of the "name" field
	streamKey := query.Get("name")
	if streamKey == "" {
		log.Println("Name field is missing")
		http.Error(w, "Name field is missing", http.StatusBadRequest)
		return
	}

	// Check if the stream key is valid or authorized
	if isValidStreamKey(streamKey) == true {
                // based on stream key get application and name of stream
		redirectStreamUrl := streamingServer + "/hls_" + application + "/" + name
		w.Header().Set("Location", redirectStreamUrl)
		w.WriteHeader(http.StatusFound)
		return
	}
	// Send an error response for invalid or unauthorized stream key
	w.WriteHeader(http.StatusForbidden)
	fmt.Fprint(w, "Stream denied")
	return
}

Took me a while to figure this out. Its primarily for a use case in which I can handle authentication and setting of stream id/pathing without having user change their streamkey ever.

Redirect it back to your nginx but to another application that actually ingests stream. Otherwise, I dont think you need to use on_publish if you dont have any sort of ceremony your streaming solution needs to do.

My understanding of on_publish_done is that fires when the stream has ended. So when the stream is complete and you have business logic for complete streams you should use that.

@narayanan-ka
Copy link
Author

narayanan-ka commented Jul 6, 2023

@lovgrandma Sorry for reverting late. Got lost in the list of notifications on Git. I did exactly Already what you have done for on_publish and on_publish done. I still cant wrap my head around on_play and on_play done. Form the directives listed here https://github.com/arut/nginx-rtmp-module/wiki/Directives#on_publish
It seems on_publish is for remote push while on_play for remote_pull. Only if we know what both terms mean from a workflow perspective ?

@Sora012
Copy link

Sora012 commented Dec 13, 2023

I know this is old issue, but "on_play" is called when someone is trying to view/read/access the stream. "on_publish" is for when someone is trying to publish a stream.

on_publish: can be used to authenticate a stream key and redirect the key to a new location for direct playback without leaking the private stream key

on_publish_done: can be used to de-auth a stream key, you could set a stream in a database as "live" from "on_publish" and then with "on_publish_done" set it as "offline"

on_play: can be used to deny if a stream is private and a wrong password is given, and to increment a view counter

on_play_done: is when a reader/viewer has finished playback. It could be used to remove a "viewer" from a live view counter.

Edit:
The above are example ideas, I imagine it could be used in a variety of really creative ways. I personally used "on_play" and "on_play_done" to increase and decrease a view counter per stream, and "on_publish" and "on_publish_done" to authenticate a stream key and if successful redirect the stream to a public username and set a stream as online, or offline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants