{"id":28061928,"url":"https://github.com/swesterfeld/audiowmark","last_synced_at":"2025-10-06T04:54:43.919Z","repository":{"id":40543266,"uuid":"255667022","full_name":"swesterfeld/audiowmark","owner":"swesterfeld","description":"Audio Watermarking","archived":false,"fork":false,"pushed_at":"2025-05-15T13:30:09.000Z","size":1105,"stargazers_count":447,"open_issues_count":16,"forks_count":88,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-19T11:06:22.989Z","etag":null,"topics":["audio-watermarking","digital-watermarking","fft","signal-processing"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swesterfeld.png","metadata":{"files":{"readme":"README.adoc","changelog":"NEWS","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-04-14T16:44:34.000Z","updated_at":"2025-05-18T18:17:54.000Z","dependencies_parsed_at":"2024-01-27T15:27:28.305Z","dependency_job_id":"5cbded31-e1e0-4b59-ad3d-21522003596e","html_url":"https://github.com/swesterfeld/audiowmark","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/swesterfeld/audiowmark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swesterfeld%2Faudiowmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swesterfeld%2Faudiowmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swesterfeld%2Faudiowmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swesterfeld%2Faudiowmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swesterfeld","download_url":"https://codeload.github.com/swesterfeld/audiowmark/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swesterfeld%2Faudiowmark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278561275,"owners_count":26006954,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio-watermarking","digital-watermarking","fft","signal-processing"],"created_at":"2025-05-12T10:31:15.333Z","updated_at":"2025-10-06T04:54:43.913Z","avatar_url":"https://github.com/swesterfeld.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"= audiowmark - Audio Watermarking\n\n== Description\n\n`audiowmark` is an Open Source (GPL) solution for audio watermarking.\n\nA sound file is read by the software, and a 128-bit message is stored in a\nwatermark in the output sound file. For human listeners, the files typically\nsound the same.\n\nHowever, the 128-bit message can be retrieved from the output sound file. Our\ntests show, that even if the file is converted to mp3 or ogg (with bitrate 128\nkbit/s or higher), the watermark usually can be retrieved without problems. The\nprocess of retrieving the message does not need the original audio file (blind\ndecoding).\n\nInternally, audiowmark is using the patchwork algorithm to hide the data in the\nspectrum of the audio file. The signal is split into 1024 sample frames. For\neach frame, some pseoudo-randomly selected amplitudes of the frequency bands of\na 1024-value FFTs are increased or decreased slightly, which can be detected\nlater. The algorithm used here is inspired by\n\n  Martin Steinebach: Digitale Wasserzeichen für Audiodaten.\n  Darmstadt University of Technology 2004, ISBN 3-8322-2507-2\n\nIf you are interested in the details how `audiowmark` works, there is\na separate\nhttps://uplex.de/audiowmark/audiowmark-developer.pdf[*documentation for developers*].\n\n== Open Source License\n\n`audiowmark` is *open source* software available under the *GPLv3\nor later* license.\n\nCopyright (C) 2018-2020 Stefan Westerfeld\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\n== Adding a Watermark\n\nTo add a watermark to the soundfile in.wav with a 128-bit message (which is\nspecified as hex-string):\n\n[subs=+quotes]\n....\n  *$ audiowmark add in.wav out.wav 0123456789abcdef0011223344556677*\n  Input:        in.wav\n  Output:       out.wav\n  Message:      0123456789abcdef0011223344556677\n  Strength:     10\n\n  Time:         3:59\n  Sample Rate:  48000\n  Channels:     2\n  Data Blocks:  4\n....\n\nIf you want to use `audiowmark` in any serious application, please read the\nsection \u003c\u003crec-payload\u003e\u003e on how to generate the 128-bit message. Typically these\nbits should be a *hash* or *HMAC* of some sort.\n\nThe most important options for adding a watermark are:\n\n--key \u003cfilename\u003e::\nUse watermarking key from file \u003cfilename\u003e (see \u003c\u003ckey\u003e\u003e).\n\n--strength \u003cs\u003e::\nSet the watermarking strength (see \u003c\u003cstrength\u003e\u003e).\n\n== Retrieving a Watermark\n\nTo get the 128-bit message from the watermarked file, use:\n\n[subs=+quotes]\n....\n  *$ audiowmark get out.wav*\n  pattern  0:05 0123456789abcdef0011223344556677 1.358 0.059 A\n  pattern  0:57 0123456789abcdef0011223344556677 1.426 0.050 B\n  pattern  0:57 0123456789abcdef0011223344556677 1.392 0.055 AB\n  pattern  1:49 0123456789abcdef0011223344556677 1.453 0.074 A\n  pattern  2:40 0123456789abcdef0011223344556677 1.359 0.080 B\n  pattern  2:40 0123456789abcdef0011223344556677 1.406 0.077 AB\n  pattern   all 0123456789abcdef0011223344556677 1.399 0.035\n  pattern  2:58 c6141f3d25720eb0dbd0e38ee2355ff4 0.185 0.382 B\n  pattern  2:14 df659ac435f0569c67cdac1fb2e36cd8 0.178 0.391 B\n  pattern  1:58 d7d7ed21e9d6da0a4ffdd5e55ffdb623 0.176 0.389 A\n  pattern  2:59 1c13f1532eeb6c9aa719253736849d6e 0.167 0.389 A\n....\nThe output of `audiowmark get` is designed to be machine readable. Each line\nthat starts with `pattern` contains one decoded message. The fields are\nseperated by one or more space characters. The first field is a *timestamp*\nindicating the position of the data block. The second field is the *decoded\nmessage*. The results are sorted by relevance, the most relevant matches\nare shown first.\n\nThe software was designed under the assumption that the message is a *hash* or\n*HMAC* of some sort. Before you start using `audiowmark` in any serious\napplication, please read the section \u003c\u003crec-payload\u003e\u003e. You - the user - should\nbe able to decide whether a message is correct or not. To do this, on\nwatermarking song files, you could *create a database entry* for each message\nyou embedded in a watermark. During retrieval, you should perform a *database\nlookup* for each pattern `audiowmark get` outputs. If the message is not found,\nthen you should assume that a decoding error occurred. In our example the\nlast results did not match the correct message and need to be ignored.\n\nThe third field is the *sync score* (higher is better). The synchronization\nalgorithm tries to find valid data blocks in the audio file, that become\ncandidates for decoding.\n\nThe fourth field is the *decoding error* (lower is better). During message\ndecoding, we use convolutional codes for error correction, to make the\nwatermarking more robust.\n\nThe fifth field is the *block type*. There are two types of data blocks,\nA blocks and B blocks. A single data block can be decoded alone, as it contains\na complete message. However, if during watermark detection an A block followed\nby a B block was found, and the two blocks are at the expected distance, these\ntwo can be decoded together (then this field will be AB), resulting in even\nhigher error correction capacity than one block alone would have.\n\nTo improve the error correction capacity even further, the `all` pattern\nmerges multiple data blocks that are found at the expected distance. The\ncombined decoded message will often be the most reliable result (meaning that\neven if all other patterns were incorrect, this could still be right).\n\nThe most important options for getting a watermark are:\n\n--key \u003cfilename\u003e::\nUse watermarking key from file \u003cfilename\u003e (see \u003c\u003ckey\u003e\u003e).\n\n--detect-speed::\n--detect-speed-patient::\nDetect and correct replay speed difference (see \u003c\u003cspeed\u003e\u003e).\n\n--json \u003cfile\u003e::\nWrite results to \u003cfile\u003e in machine readable JSON format.\n\n--chunk-size \u003cminutes\u003e::\nSet chunk size for memory/speed tradeoff. Larger chunk sizes result in\nfaster detection but higher memory usage. Default: 30 minutes.\n\n--sync-threshold \u003ct\u003e::\nSet threshold for minimum sync quality. Patterns with sync scores higher than\nthis threshold are considered relevant and are decoded. The default (0.35) is\nusually fine.\n\n--n-best \u003cn\u003e::\nIn addition to all patterns that are considered relevant due to their sync\nscore, this parameter ensures that at least \u003cn\u003e matches are decoded, even if\ntheir sync score is low. This can help in situations where the quality of the\ninput material is low, so that no patterns have a high enough sync score to be\nconsidered relevant. On the other hand this makes watermark detection slower,\nespecially when many keys are used, so if performance is more important than\naccuracy, using `--n-best 0` can be used to disable n-best decoding.  Default:\nat least decode 8 matches.\n\n[[key]]\n== Watermark Key\n\nSince the software is Open Source, a watermarking key should be used to ensure\nthat the message bits cannot be retrieved by somebody else (which would also\nallow removing the watermark without loss of quality). The watermark key\ncontrols all pseudo-random parameters of the algorithm. This means that\nit determines which frequency bands are increased or decreased to store a\n0 bit or a 1 bit. Without the key, it is impossible to decode the message\nbits from the audio file alone.\n\nOur watermarking key is a 128-bit AES key. A key can be generated using\n\n  audiowmark gen-key test.key\n\nand can be used for the add/get commands as follows:\n\n  audiowmark add --key test.key in.wav out.wav 0123456789abcdef0011223344556677\n  audiowmark get --key test.key out.wav\n\nKeys can be named using the `gen-key --name` option, and the key name will be\nreported for each match:\n\n  audiowmark gen-key oct23.key --name \"October 2023\"\n\nFinally, it is possible to use the `--key` option more than once for watermark\ndetection. In this case, all keys that are specified will be tried. This is\nuseful if you change keys on a regular basis, and passing multiple keys is\nmore efficient than performing watermark detection multiple times with one\nkey.\n\n  audiowmark get --key oct23.key --key nov23.key --key dec23.key out.wav\n\n[[strength]]\n== Watermark Strength\n\nThe watermark strength parameter affects how much the watermarking algorithm\nmodifies the input signal. A stronger watermark is more audible, but also more\nrobust against modifications. The default strength is 10. A watermark with that\nstrength is recoverable after mp3/ogg encoding with 128kbit/s or higher. In our\ninformal listening tests, this setting also has a very good subjective quality.\n\nA higher strength (for instance 15) would be helpful for instance if robustness\nagainst multiple conversions or conversions to low bit rates (i.e. 64kbit/s) is\ndesired.\n\nA lower strength (for instance 6) makes the watermark less audible, but also\nless robust. Strengths below 5 are not recommended. The strength has to be\nprovided for `audiowmark add`. Fractional strengths (like 7.5) are possible.\n\n  audiowmark add --strength 15 in.wav out.wav 0123456789abcdef0011223344556677\n\n[[rec-payload]]\n== Recommendations for the Watermarking Payload\n\nAlthough `audiowmark` does not specify what the 128-bit message stored in the\nwatermark should be, it was designed under the assumption that the message\nshould be a *hash* or *HMAC* of some sort.\n\nLets look at a typical use case. We have a song called *Dreams* by an artist\ncalled *Alice*. A user called *John Smith* downloads a watermarked copy.\n\nLater, we find this file somewhere on the internet. Typically we want to answer\nthe questions:\n\n * is this one of the files we previously watermarked?\n * what song/artist is this?\n * which user shared it?\n\n_When the user downloads a watermarked copy_, we construct a string that\ncontains all information we need to answer our questions, for example\nlike this:\n\n  Artist:Alice|Title:Dreams|User:John Smith\n\nTo obtain the 128-bit message, we can hash this string, for instance by\nusing the first 128 bits of a SHA-256 hash like this:\n\n  $ STRING='Artist:Alice|Title:Dreams|User:John Smith'\n  $ MSG=`echo -n \"$STRING\" | sha256sum | head -c 32`\n  $ echo $MSG\n  ecd057f0d1fbb25d6430b338b5d72eb2\n\nThis 128-bit message can be used as watermark:\n\n  $ audiowmark add --key my.key song.wav song.wm.wav $MSG\n\nAt this point, we should also *create a database entry* consisting of the\nhash value `$MSG` and the corresponding string `$STRING`.\n\nThe shell commands for creating the hash are listed here to provide a\nsimplified example. Fields (like the song title) can contain the characters `'`\nand `|`, so these cases need to be dealt with.\n\n_If we find a watermarked copy of the song on the net_, the first step is to\ndetect the watermark message using\n\n  $ audiowmark get --key my.key song.wm.wav\n  pattern  0:05 ecd057f0d1fbb25d6430b338b5d72eb2 1.377 0.068 A\n  pattern  0:57 ecd057f0d1fbb25d6430b338b5d72eb2 1.392 0.109 B\n  [...]\n\nThe second step is to perform a *database lookup* for each result returned by\n`audiowmark`. If we find a matching entry in our database, this is one of the\nfiles we previously watermarked.\n\nAs a last step, we can use the string stored in the database, which contains\nthe song/artist and the user that shared it.\n\n_The advantages of using a hash as message are:_\n\n1. Although `audiowmark` sometimes produces *false positives*, this doesn't\nmatter, because it is extremely unlikely that a false positive will match an\nexisting database entry.\n\n2. Even if a few *bit errors* occur, it is extremely unlikely that a song\nwatermarked for user A will be attributed to user B, simply because all hash\nbits depend on the user. So this is a much better payload than storing a user\nID, artist ID and song ID in the message bits directly.\n\n3. It is *easy to extend*, because we can add any fields we need to the hash\nstring. For instance, if we want to store the name of the album, we can simply\nadd it to the string.\n\n4. If the hash matches exactly, it is really *hard to deny* that it was this\nuser who shared the song. How else could all 128 bits of the hash match the\nmessage bits decoded by `audiowmark`?\n\n[[speed]]\n== Speed Detection\n\nIf a watermarked audio signal is played back a little faster or slower than the\noriginal speed, watermark detection will fail. This could happen by accident if\nthe digital watermark was converted to an analog signal and back and the\noriginal speed was not (exactly) preserved. It could also be done intentionally\nas an attack to avoid the watermark from being detected.\n\nIn order to be able to find the watermark in these cases, `audiowmark` can try\nto figure out the speed difference to the original audio signal and correct the\nreplay speed before detecting the watermark. The search range for the replay\nspeed is approximately *[0.8..1.25]*.\n\nExample: add a watermark to `in.wav` and increase the replay speed by 5% using\n`sox`.\n[subs=+quotes]\n....\n  *$ audiowmark add in.wav out.wav 0123456789abcdef0011223344556677*\n  [...]\n  *$ sox out.wav out1.wav speed 1.05*\n....\n\nWithout speed detection, we get no results. With speed detection the speed\ndifference is detected and corrected so we get results.\n[subs=+quotes]\n....\n  *$ audiowmark get out1.wav*\n  *$ audiowmark get out1.wav --detect-speed*\n  speed 1.049966\n  pattern  0:05 0123456789abcdef0011223344556677 1.209 0.147 A-SPEED\n  pattern  0:57 0123456789abcdef0011223344556677 1.301 0.143 B-SPEED\n  pattern  0:57 0123456789abcdef0011223344556677 1.255 0.145 AB-SPEED\n  pattern  1:49 0123456789abcdef0011223344556677 1.380 0.173 A-SPEED\n  pattern   all 0123456789abcdef0011223344556677 1.297 0.130 SPEED\n....\n\nThe speed detection algorithm is not enabled by default because it is\nrelatively slow (total cpu time required) and needs a lot of memory. However\nthe search is automatically run in parallel using many threads on systems with\nmany cpu cores. So on good hardware it makes sense to always enable this option\nto be robust to replay speed attacks.\n\nThere are two versions of the speed detection algorithm, `--detect-speed` and\n`--detect-speed-patient`. The difference is that the patient version takes\nmore cpu time to detect the speed, but produces more accurate results.\n\n== Short Payload (deprecated)\n\n**The support for short payload is now deprecated and will probably be removed in\nsome newer version**, mainly because with a 128-bit HMAC based message, you can\nreally be 100% certain that there are no false positives, so that if you see a\ncertain payload, you can be sure that it was the watermark that was originally\nadded. For short payload, there is a (very very small) probablity for\ngenerating a false positive, and there is no way of detecting it if this has\nhappened.\n\nBy default, the watermark will store a 128-bit message. In this mode, we\nrecommend using a 128bit hash (or HMAC) as payload. No error checking is\nperformed, the user needs to test patterns that the watermarker decodes to\nensure that they really are one of the expected patterns, not a decoding\nerror.\n\nAs an alternative, an experimental short payload option is available, for very\nshort payloads (12, 16 or 20 bits). It is enabled using the `--short \u003cbits\u003e`\ncommand line option, for instance for 16 bits:\n\n  audiowmark add --short 16 in.wav out.wav abcd\n  audiowmark get --short 16 out.wav\n\nInternally, a larger set of bits is sent to ensure that decoded short patterns\nare really valid, so in this mode, error checking is performed after decoding,\nand only valid patterns are reported.\n\nBesides error checking, the advantage of a short payload is that fewer bits\nneed to be sent, so decoding will more likely to be successful on shorter\nclips.\n\n== Video Files\n\nFor video files, `videowmark` can be used to add a watermark to the audio track\nof video files. To add a watermark, use\n\n[subs=+quotes]\n....\n  *$ videowmark add in.avi out.avi 0123456789abcdef0011223344556677*\n  Audio Codec:  -c:a mp3 -ab 128000\n  Input:        in.avi\n  Output:       out.avi\n  Message:      0123456789abcdef0011223344556677\n  Strength:     10\n\n  Time:         3:53\n  Sample Rate:  44100\n  Channels:     2\n  Data Blocks:  4\n....\n\nTo detect a watermark, use\n\n[subs=+quotes]\n....\n  *$ videowmark get out.avi*\n  pattern  0:05 0123456789abcdef0011223344556677 1.294 0.142 A\n  pattern  0:57 0123456789abcdef0011223344556677 1.191 0.144 B\n  pattern  0:57 0123456789abcdef0011223344556677 1.242 0.145 AB\n  pattern  1:49 0123456789abcdef0011223344556677 1.215 0.120 A\n  pattern  2:40 0123456789abcdef0011223344556677 1.079 0.128 B\n  pattern  2:40 0123456789abcdef0011223344556677 1.147 0.126 AB\n  pattern   all 0123456789abcdef0011223344556677 1.195 0.104\n....\n\nThe key and strength can be set using the command line options\n\n--key \u003cfilename\u003e::\nUse watermarking key from file \u003cfilename\u003e (see \u003c\u003ckey\u003e\u003e).\n\n--strength \u003cs\u003e::\nSet the watermarking strength (see \u003c\u003cstrength\u003e\u003e).\n\nVideos can be watermarked on-the-fly using \u003c\u003chls\u003e\u003e.\n\n== Output as Stream\n\nUsually, an input file is read, watermarked and an output file is written.\nThis means that it takes some time before the watermarked file can be used.\n\nAn alternative is to output the watermarked file as stream to stdout. One use\ncase is sending the watermarked file to a user via network while the\nwatermarker is still working on the rest of the file. Here is an example how to\nwatermark a wav file to stdout:\n\n  audiowmark add in.wav - 0123456789abcdef0011223344556677 | play -\n\nIn this case the file in.wav is read, watermarked, and the output is sent\nto stdout. The \"play -\" can start playing the watermarked stream while the\nrest of the file is being watermarked.\n\nIf - is used as output, the output is a valid .wav file, so the programs\nrunning after `audiowmark` will be able to determine sample rate, number of\nchannels, bit depth, encoding and so on from the wav header.\n\nNote that all input formats supported by audiowmark can be used in this way,\nfor instance flac/mp3:\n\n  audiowmark add in.flac - 0123456789abcdef0011223344556677 | play -\n  audiowmark add in.mp3 - 0123456789abcdef0011223344556677 | play -\n\n== Input from Stream\n\nSimilar to the output, the `audiowmark` input can be a stream. In this case,\nthe input must be a valid .wav file. The watermarker will be able to\nstart watermarking the input stream before all data is available. An\nexample would be:\n\n  cat in.wav | audiowmark add - out.wav 0123456789abcdef0011223344556677\n\nIt is possible to do both, input from stream and output as stream.\n\n  cat in.wav | audiowmark add - - 0123456789abcdef0011223344556677 | play -\n\nStreaming input is also supported for watermark detection.\n\n  cat in.wav | audiowmark get -\n\n== Wav Pipe Format\n\nIn some cases, the length of the streaming input is not known by the program\nthat produces the stream. For instance consider a mp3 that is being decoded by\nmadplay.\n\n  cat in.mp3 |\n    madplay -o wave:- - |\n    audiowmark add - out.wav f0\n\nSince madplay doesn't know the length of the output when it starts decoding the\nmp3, the best it can do is to fill the wav header with a big number. And\nindeed, audiowmark will watermark the stream, but also print a warning like\nthis:\n\n  audiowmark: warning: unexpected EOF; input frames (1073741823) != output frames (8316288)\n\nThis may sound harmless, but for very long input streams, this will also\ntruncate the audio input after this length. If you already know that you need\nto input a wav file from a pipe (without correct length in the header) and\nsimply want to watermark all of it, it is better to use the `wav-pipe` format:\n\n  cat in.mp3 |\n    madplay -o wave:- - |\n    audiowmark add --input-format wav-pipe --output-format rf64 - out.wav f0\n\nThis will not print a warning, and it also works correctly for long input\nstreams. Note that using `rf64` as output format is necessary for huge output\nfiles (larger than 4G).\n\nSimilar to pipe input, audiowmark can write a wav header with a huge number (in\ncases where it does not know the length in advance) if the output format is set\nto `wav-pipe`.\n\n  cat in.mp3 |\n    madplay -o wave:- - |\n    audiowmark add --input-format wav-pipe --output-format wav-pipe - - f0 |\n    lame - \u003e out.mp3\n\nIf you need both, `wav-pipe` input and output, a shorter way to write it is\nusing `--format wav-pipe`, like this:\n\n  cat in.mp3 |\n    madplay -o wave:- - |\n    audiowmark add --format wav-pipe - - f0 |\n    lame - \u003e out.mp3\n\n== Raw Streams\n\nSo far, all streams described here are essentially wav streams, which means\nthat the wav header allows `audiowmark` to determine sample rate, number of\nchannels, bit depth, encoding and so forth from the stream itself, and the a\nwav header is written for the program after `audiowmark`, so that this can\nfigure out the parameters of the stream.\n\nIf the program before or after `audiowmark` doesn't support wav headers, raw\nstreams can be used instead. The idea is to set all information that is needed\nlike sample rate, number of channels,... manually.  Then, headerless data can\nbe processed from stdin and/or sent to stdout.\n\n--input-format raw::\n--output-format raw::\n--format raw::\n\nThese can be used to set the input format or output format to raw. The\nlast version sets both, input and output format to raw.\n\n--raw-rate \u003crate\u003e::\n\nThis should be used to set the sample rate. The input sample rate and\nthe output sample rate will always be the same (no resampling is\ndone by the watermarker). There is no default for the sampling rate,\nso this parameter must always be specified for raw streams.\n\n--raw-input-bits \u003cbits\u003e::\n--raw-output-bits \u003cbits\u003e::\n--raw-bits \u003cbits\u003e::\n\nThe options can be used to set the input number of bits, the output number of\nbits or both. The number of bits can be `16`, `24` or `32`. The default number\nof bits is `16`.\n\n--raw-input-endian \u003cendian\u003e::\n--raw-output-endian \u003cendian\u003e::\n--raw-endian \u003cendian\u003e::\n\nThese options can be used to set the input/output endianness or both.\nThe \u003cendian\u003e parameter can either be `little` or `big`. The default\nendianness is `little`.\n\n--raw-input-encoding \u003cencoding\u003e::\n--raw-output-encoding \u003cencoding\u003e::\n--raw-encoding \u003cencoding\u003e::\n\nThese options can be used to set the input/output encoding or both.  The\n\u003cencoding\u003e parameter can be `signed`, `unsigned`, `float` or `double`. The\ndefault encoding is `signed`. Using `float` (or `double`) encoding\nautomatically sets the number of bits to `32` (or `64`).\n\n--raw-channels \u003cchannels\u003e::\n\nThis can be used to set the number of channels. Note that the number\nof input channels and the number of output channels must always be the\nsame. The watermarker has been designed and tested for stereo files,\nso the number of channels should really be `2`. This is also the\ndefault.\n\n== Other Command Line Options\n\n--output-format rf64::\n\nRegular wav files are limited to 4GB in size. By using this option,\n`audiowmark` will write RF64 wave files, which do not have this size limit.\nThis is not the default because not all programs might be able to read RF64\nwave files.\n\n--q, --quiet::\n\nDisable all information messages generated by `audiomark`.\n\n--strict::\n\nThis option will enable strict error checking, which may in some situations\nmake `audiowmark` return an error, where it could continue.\n\n[[hls]]\n== HTTP Live Streaming\n\n=== Introduction for HLS\n\nHTTP Live Streaming (HLS) is a protocol to deliver audio or video streams via\nHTTP.  One example for using HLS in practice would be: a user watches a video\nin a web browser with a player like `hls.js`. The user is free to\nplay/pause/seek the video as he wants. `audiowmark` can watermark the audio\ncontent while it is being transmitted to the user.\n\nHLS splits the contents of each stream into small segments. For the watermarker\nthis means that if the user seeks to a position far ahead in the stream, the\nserver needs to start sending segments from where the new play position is, but\neverything in between can be ignored.\n\nAnother important property of HLS is that it allows separate segments for the\nvideo and audio stream of a video. Since we watermark only the audio track of a\nvideo, the video segments can be sent as they are (and different users can get\nthe same video segments). What is watermarked are the audio segments only, so\nhere instead of sending the original audio segments to the user, the audio\nsegments are watermarked individually for each user, and then transmitted.\n\nEverything necessary to watermark HLS audio segments is available within\n`audiowmark`. The server side support which is necessary to send the right\nwatermarked segment to the right user is not included.\n\n[[hls-requirements]]\n=== HLS Requirements\n\nHLS support requires some headers/libraries from ffmpeg:\n\n* libavcodec\n* libavformat\n* libavutil\n* libswresample\n\nTo enable these as dependencies and build `audiowmark` with HLS support, use the\n`--with-ffmpeg` configure option:\n\n[subs=+quotes]\n....\n*$ ./configure --with-ffmpeg*\n....\n\nIn addition to the libraries, `audiowmark` also uses the two command line\nprograms from ffmpeg, so they need to be installed:\n\n* ffmpeg\n* ffprobe\n\n=== Preparing HLS segments\n\nThe first step for preparing content for streaming with HLS would be splitting\na video into segments. For this documentation, we use a very simple example\nusing ffmpeg. No matter what the original codec was, at this point we force\ntranscoding to AAC with our target bit rate, because during delivery the stream\nwill be in AAC format.\n\n[subs=+quotes]\n....\n*$ ffmpeg -i video.mp4 -f hls -master_pl_name replay.m3u8 -c:a aac -ab 192k \\\n  -var_stream_map \"a:0,agroup:aud v:0,agroup:aud\" \\\n  -hls_playlist_type vod -hls_list_size 0 -hls_time 10 vs%v/out.m3u8*\n....\n\nThis splits the `video.mp4` file into an audio stream of segments in the `vs0`\ndirectory and a video stream of segments in the `vs1` directory. Each segment\nis approximately 10 seconds long, and a master playlist is written to\n`replay.m3u8`.\n\nNow we can add the relevant audio context to each audio ts segment. This is\nnecessary so that when the segment is watermarked in order to be transmitted to\nthe user, `audiowmark` will have enough context available before and after the\nsegment to create a watermark which sounds correct over segment boundaries.\n\n[subs=+quotes]\n....\n*$ audiowmark hls-prepare vs0 vs0prep out.m3u8 video.mp4*\nAAC Bitrate:  195641 (detected)\nSegments:     18\nTime:         2:53\n....\n\nThis steps reads the audio playlist `vs0/out.m3u8` and writes all segments\ncontained in this audio playlist to a new directory `vs0prep` which\ncontains the audio segments prepared for watermarking.\n\nThe last argument in this command line is `video.mp4` again. All audio\nthat is watermarked is taken from this audio master. It could also be\nsupplied in `wav` format. This makes a difference if you use lossy\ncompression as target format (for instance AAC), but your original\nvideo has an audio stream with higher quality (i.e. lossless).\n\n=== Watermarking HLS segments\n\nSo with all preparations made, what would the server have to do to send a\nwatermarked version of the 6th audio segment `vs0prep/out5.ts`?\n\n[subs=+quotes]\n....\n*$ audiowmark hls-add vs0prep/out5.ts send5.ts 0123456789abcdef0011223344556677*\nMessage:      0123456789abcdef0011223344556677\nStrength:     10\n\nTime:         0:15\nSample Rate:  44100\nChannels:     2\nData Blocks:  0\nAAC Bitrate:  195641\n....\n\nSo instead of sending out5.ts (which has no watermark) to the user, we would\nsend send5.ts, which is watermarked.\n\nIn a real-world use case, it is likely that the server would supply the input\nsegment on stdin and send the output segment as written to stdout, like this\n\n[subs=+quotes]\n....\n*$ [...] | audiowmark hls-add - - 0123456789abcdef0011223344556677 | [...]*\n[...]\n....\n\nThe usual parameters are supported in `audiowmark hls-add`, like\n\n--key \u003cfilename\u003e::\nUse watermarking key from file \u003cfilename\u003e (see \u003c\u003ckey\u003e\u003e).\n\n--strength \u003cs\u003e::\nSet the watermarking strength (see \u003c\u003cstrength\u003e\u003e).\n\nThe AAC bitrate for the output segment can be set using:\n\n--bit-rate \u003cbit_rate\u003e::\nSet the AAC bit-rate for the generated watermarked segment.\n\nThe rules for the AAC bit-rate of the newly encoded watermarked segment are:\n\n* if the --bit-rate option is used during `hls-add`, this bit-rate will be used\n* otherwise, if the `--bit-rate` option is used during `hls-prepare`, this bit-rate will be used\n* otherwise, the bit-rate of the input material is detected during `hls-prepare`\n\n== Compiling from Source\n\nStable releases are available from http://uplex.de/audiowmark\n\nThe steps to compile the source code are:\n\n        ./configure\n        make\n        make install\n\nIf you build from git (which doesn't include `configure`), the first\nstep is `./autogen.sh`. In this case, you need to ensure that (besides\nthe dependencies listed below) the `autoconf-archive` package is\ninstalled.\n\n== Compiling from Source on Windows/Cygwin\n\nWindows is not an officially supported platform. However, if you want to\nbuild audiowmark (and videowmark) from source on windows, one way to do\nso is to use Cygwin. Andreas Strohmeier provided\nhttps://raw.githubusercontent.com/swesterfeld/audiowmark/master/docs/win-x64-build-guide.txt[*build instructions for Cygwin*].\n\n== Dependencies\n\nIf you compile from source, `audiowmark` needs the following libraries:\n\n* libfftw3\n* libsndfile\n* libgcrypt\n* libzita-resampler\n* libmpg123\n\nIf you want to build with HTTP Live Streaming support, see also\n\u003c\u003chls-requirements\u003e\u003e.\n\n== Building fftw\n\n`audiowmark` needs the single prevision variant of fftw3.\n\nIf you are building fftw3 from source, use the `--enable-float`\nconfigure parameter to build it, e.g.::\n\n\tcd ${FFTW3_SOURCE}\n\t./configure --enable-float --enable-sse \u0026\u0026 \\\n\tmake \u0026\u0026 \\\n\tsudo make install\n\nor, when building from git\n\n\tcd ${FFTW3_GIT}\n\t./bootstrap.sh --enable-shared --enable-sse --enable-float \u0026\u0026 \\\n\tmake \u0026\u0026 \\\n\tsudo make install\n\n== Docker Build\n\nYou should be able to execute `audiowmark` via Docker.\nExample that outputs the usage message:\n\n  docker build -t audiowmark .\n  docker run -v \u003clocal-data-directory\u003e:/data --rm -i audiowmark -h\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswesterfeld%2Faudiowmark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswesterfeld%2Faudiowmark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswesterfeld%2Faudiowmark/lists"}