Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SOURCES += src/testing.moon
SOURCES += src/util.moon
SOURCES += src/video_to_screen.moon
SOURCES += src/vp8_twopass_log_patcher.moon
SOURCES += src/upload.moon
SOURCES += src/formats/base.moon
SOURCES += src/formats/rawvideo.moon
SOURCES += src/formats/webm.moon
Expand All @@ -18,6 +19,7 @@ SOURCES += src/formats/gif.moon
SOURCES += src/formats/webp.moon
SOURCES += src/Page.moon
SOURCES += src/EncodeWithProgress.moon
SOURCES += src/UploadWithProgress.moon
SOURCES += src/encode.moon
SOURCES += src/CropPage.moon
SOURCES += src/EncodeOptionsPage.moon
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ By default, the script is activated by the W (shift+w) key.
## Usage
Follow the on-screen instructions. Encoded WebM files will have audio/subs based on the current playback options (i.e. will be muted if no audio, won't have hardcoded subs if subs aren't visible).

### Uploading

Press `u` (encode & upload) on the WebM maker page to encode a clip and upload it in one step. The destination is set in the options (`o`) and stored in `webm.conf`:

- `upload_host` — `catbox` (permanent) or `litterbox` (temporary).
- `litterbox_time` — expiry for litterbox uploads: `1h`, `12h`, `24h` or `72h`.
- `catbox_userhash` — optional Catbox account hash; account uploads are permanent and manageable.
- `upload_curl_path` — the `curl` executable used for the multipart upload.
- `open_after_upload` — open the link in the browser as soon as it is ready.

Uploads use `curl`; when it is not on `PATH`, the `u` line is hidden. The resulting URL is copied to the clipboard (mpv's `clipboard/text` when available, otherwise `wl-copy`, `xclip` or `pbcopy`). Only the Catbox services are supported: Streamable requires an account for uploads, so it is not offered.

## Configuration
You can configure the script's defaults by either changing the `options` at the beginning of the script, or placing a `webm.conf` inside the `script-opts` directory. A sample `webm.conf` file with the default options can be found [here][conf]. Note that you don't need to specify all options, only the ones you wish to override.

Expand Down
4 changes: 4 additions & 0 deletions src/EncodeOptionsPage.moon
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ class EncodeOptionsPage extends Page
formatOpts =
possibleValues: [{fId, formats[fId].displayName} for fId in *formatIds]

uploadHostOpts =
possibleValues: upload_host_possible_values!

gifDitherOpts =
possibleValues: {{0, "bayer_scale 0"}, {1, "bayer_scale 1"},
{2, "bayer_scale 2"}, {3, "bayer_scale 3"}, {4, "bayer_scale 4"}, {5, "bayer_scale 5"}, {6, "sierra2_4a"}}
Expand All @@ -166,6 +169,7 @@ class EncodeOptionsPage extends Page
-- by dicts on Lua.
@options = {
{"output_format", Option("list", "Output Format", options.output_format, formatOpts)}
{"upload_host", Option("list", "Upload Destination", options.upload_host, uploadHostOpts, -> is_upload_available!)}
{"twopass", Option("bool", "Two Pass", options.twopass)},
{"apply_current_filters", Option("bool", "Apply Current Video Filters", options.apply_current_filters)}
{"scale_height", Option("list", "Scale Height", options.scale_height, scaleHeightOpts)},
Expand Down
34 changes: 33 additions & 1 deletion src/MainPage.moon
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class MainPage extends Page
"o": self\changeOptions
"p": self\preview
"e": self\encode
"u": self\upload
"ESC": self\hide
@startTime = -1
@endTime = -1
Expand Down Expand Up @@ -60,7 +61,9 @@ class MainPage extends Page
ass\append("#{bold('@:')} jump to end time\\N")
ass\append("#{bold('o:')} change encode options\\N")
ass\append("#{bold('p:')} preview\\N")
ass\append("#{bold('e:')} encode\\N\\N")
ass\append("#{bold('e:')} encode\\N")
ass\append("#{bold('u:')} encode & upload\\N") if is_upload_available!
ass\append("\\N")
ass\append("#{bold('ESC:')} close\\N")
mp.set_osd_ass(window_w, window_h, ass.text)

Expand Down Expand Up @@ -95,6 +98,35 @@ class MainPage extends Page
previewPage = PreviewPage(self\onPreviewEnded, @region, @startTime, @endTime)
previewPage\show!

onEncodedForUpload: (success, outPath) =>
if not success or not outPath
self\show!
return
uploadPage = UploadWithProgress(self\onUploadEnded, outPath)
uploadPage\show!

onUploadEnded: (state) =>
if state == "options"
self\changeOptions!
else
self\show!

upload: =>
if not is_upload_available!
message("Uploads need curl on PATH. Set upload_curl_path in webm.conf.")
return
if @startTime < 0
message("No start time, aborting")
return
if @endTime < 0
message("No end time, aborting")
return
if @startTime >= @endTime
message("Start time is ahead of end time, aborting")
return
self\hide!
encode(@region, @startTime, @endTime, self\onEncodedForUpload)

encode: =>
self\hide!
if @startTime < 0
Expand Down
156 changes: 156 additions & 0 deletions src/UploadWithProgress.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
-- Progress, done and failed states for a single upload. Not an encode page: it
-- runs the curl subprocess asynchronously so ESC can abort it and the progress
-- percentage keeps redrawing.
class UploadWithProgress extends Page
-- callback(state) where state is "done", "failed", "cancelled" or "options".
new: (callback, path) =>
@callback = callback
@path = path
_, @filename = utils.split_path(path)
info = utils.file_info(path)
@sizeText = info and string.format("%.1f MB", info.size / 1000000) or "unknown size"
@responsePath = os.tmpname()
@progressPath = os.tmpname()
@state = "uploading"
@percent = 0
@finished = false
@cancelled = false
@keybinds =
"ESC": self\onEscape
"c": self\copyAgain
"o": self\openSomething
"r": self\retry

prepare: =>
self\startUpload!

dispose: =>
self\stopTimer!
os.remove(@responsePath) if @responsePath
os.remove(@progressPath) if @progressPath

stopTimer: =>
if @timer
@timer\kill!
@timer = nil

startUpload: =>
@state = "uploading"
@percent = 0
@finished = false
@cancelled = false
@host = get_upload_host(options.upload_host)

-- Clear a stale progress meter from a previous attempt.
file = io.open(@progressPath, "w")
file\close! if file

args = build_upload_args(@path, options.upload_host, @responsePath, @progressPath)
@timer = mp.add_periodic_timer(0.2, self\pollProgress)
@handle = mp.command_native_async({
name: "subprocess"
args: args
playback_only: false
capture_stdout: true
capture_stderr: false
capture_size: 128
}, self\onFinished)

pollProgress: =>
return if @state != "uploading"
content = read_file(@progressPath)
return if not content or content == ""
percent = nil
for match in content\gmatch("(%d+%.?%d*)%%")
percent = tonumber(match)
if percent and math.floor(percent) != @percent
@percent = math.floor(percent)
self\draw!

onFinished: (success, result, error) =>
return if @finished
@finished = true
self\stopTimer!

if @cancelled
emit_event("upload-finished", "cancelled")
self\finish("cancelled")
return

httpCode = result and tonumber(result.stdout)
response = trim(read_file(@responsePath) or "")
uploadOk = success and result and result.status == 0 and
httpCode and httpCode >= 200 and httpCode < 300 and
response\match("^https?://")

if uploadOk
@url = response
@state = "done"
pcall(() -> copy_to_clipboard(@url))
pcall(() -> open_url(@url)) if options.open_after_upload
else
@state = "failed"
@errorMessage = response
if @errorMessage == ""
@errorMessage = (result and result.error_string) or tostring(error) or "upload failed"
@errorMessage = @errorMessage\gsub("%s+", " ")\sub(1, 300)
emit_event("upload-finished", @state)
self\draw!

onEscape: =>
if @state == "uploading"
@cancelled = true
self\stopTimer!
mp.abort_async_command(@handle) if @handle
-- If the abort never reports back, close anyway.
mp.add_timeout(0.5, (-> self\finish("cancelled") if not @closing))
else
self\finish(@state)

-- Only meaningful on the done page.
copyAgain: =>
if @state == "done" and @url
copy_to_clipboard(@url)
message("Link copied to clipboard.")

-- Open the result on the done page; jump to the options on the failed page.
openSomething: =>
if @state == "done" and @url
open_url(@url)
elseif @state == "failed"
self\finish("options")

retry: =>
self\startUpload! if @state == "failed"

finish: (state) =>
return if @closing
@closing = true
self\hide!
@callback(state)

draw: =>
window_w, window_h = mp.get_osd_size()
ass = assdraw.ass_new()
ass\new_event()
self\setup_text(ass)
if @state == "uploading"
ass\append("Uploading (#{bold("#{@percent}%")})\\N")
ass\append("#{@filename}\\N")
ass\append("#{@sizeText} to #{@host.label}\\N\\N")
ass\append("#{bold('ESC:')} cancel upload\\N")
elseif @state == "done"
ass\append("#{bold('Upload complete')}\\N\\N")
ass\append("#{@url}\\N")
ass\append("Link copied to clipboard.\\N\\N")
ass\append("#{bold('c:')} copy link again\\N")
ass\append("#{bold('o:')} open in browser\\N")
ass\append("#{bold('ESC:')} close\\N")
elseif @state == "failed"
ass\append("#{bold('Upload failed')}\\N\\N")
ass\append("#{@errorMessage}\\N")
ass\append("The clip is still saved locally.\\N\\N")
ass\append("#{bold('r:')} retry upload\\N")
ass\append("#{bold('o:')} change upload options\\N")
ass\append("#{bold('ESC:')} close\\N")
mp.set_osd_ass(window_w, window_h, ass.text)
9 changes: 7 additions & 2 deletions src/encode.moon
Original file line number Diff line number Diff line change
Expand Up @@ -290,16 +290,18 @@ check_encoder = ->
emit_event("encode-finished", "fail", explanation)
return false

encode = (region, startTime, endTime) ->
encode = (region, startTime, endTime, onDone) ->
format = formats[options.output_format]
if not check_encoder!
onDone(false) if onDone
return

originalStartTime = startTime
originalEndTime = endTime
path, is_stream, is_temporary, startTime, endTime = find_path(startTime, endTime)
if not path
message("No file is being played")
onDone(false) if onDone
return

command = {
Expand Down Expand Up @@ -419,6 +421,7 @@ encode = (region, startTime, endTime) ->
if not res
message("First pass failed! Check the logs for details.")
emit_event("encode-finished", "fail")
onDone(false) if onDone

return

Expand All @@ -437,7 +440,7 @@ encode = (region, startTime, endTime) ->
msg.info("Encoding to", out_path)
msg.verbose("Command line:", table.concat(command, " "))

if options.run_detached
if options.run_detached and not onDone
message("Started encode, process was detached.")
utils.subprocess_detached({args: command})
else
Expand All @@ -453,9 +456,11 @@ encode = (region, startTime, endTime) ->
emit_event("encode-finished", "success")
if options.completion_command != ""
mp.command(options.completion_command\gsub("%%{output}", out_path))
onDone(true, out_path) if onDone
else
message("Encode failed! Check the logs for details.")
emit_event("encode-finished", "fail")
onDone(false) if onDone


-- Clean up pass log file.
Expand Down
13 changes: 13 additions & 0 deletions src/options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ local options = {
-- MPV command to run upon successful encoding
-- %{output} will be replaced with the path to the resulting file.
completion_command = "",
-- Where "encode & upload" (u) sends the clip. Only the Catbox services are
-- supported: "catbox" (permanent until 2 years of inactivity) or
-- "litterbox" (temporary, expires after litterbox_time).
upload_host = "catbox",
-- Expiry for litterbox uploads: 1h, 12h, 24h or 72h.
litterbox_time = "24h",
-- Optional Catbox account hash. Account uploads are permanent and can be
-- managed (deleted) from the Catbox account.
catbox_userhash = "",
-- curl executable used for the multipart upload.
upload_curl_path = "curl",
-- Open the uploaded link in the browser as soon as it is ready.
open_after_upload = false,
}

mpopts.read_options(options)
1 change: 1 addition & 0 deletions src/testing.moon
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ register_test_handlers = (main_page) ->
emit_event("range-set")
)
mp.register_script_message("mpv-webm-encode", -> main_page\encode!)
mp.register_script_message("mpv-webm-upload", -> main_page\upload!)
mp.register_script_message("mpv-webm-get-state", ->
mouse_x, mouse_y = mp.get_mouse_pos!
osd_w, osd_h = mp.get_osd_size!
Expand Down
Loading
Loading