Modules
50 |ffmpeg | 53 |Lua bindings to FFmpeg libraries. | 54 |
ffmpeg.torch | 57 |Torch utilities for Lua bindings to FFmpeg libraries. | 58 |
Topics
61 |README.md | 64 |65 | |
LICENSE | 68 |69 | |
├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── build_and_test.sh ├── config.ld ├── doc ├── index.html ├── ldoc.css ├── modules │ ├── ffmpeg.html │ ├── ffmpeg.torch.html │ ├── monad.html │ ├── monad.result.html │ └── result.html └── topics │ ├── LICENSE.html │ └── README.md.html ├── docker-compose.yml ├── rockspecs └── ffmpeg-ffi-scm-0.rockspec ├── src └── ffmpeg │ ├── ffmpeg.lua │ └── torch.lua └── test ├── download_test_data.sh ├── ffmpeg_spec.lua └── ffmpeg_torch_spec.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | *.rock 9 | 10 | # Object files 11 | *.o 12 | *.os 13 | *.ko 14 | *.obj 15 | *.elf 16 | 17 | # Precompiled Headers 18 | *.gch 19 | *.pch 20 | 21 | # Libraries 22 | *.lib 23 | *.a 24 | *.la 25 | *.lo 26 | *.def 27 | *.exp 28 | 29 | # Shared objects (inc. Windows DLLs) 30 | *.dll 31 | *.so 32 | *.so.* 33 | *.dylib 34 | 35 | # Executables 36 | *.exe 37 | *.out 38 | *.app 39 | *.i*86 40 | *.x86_64 41 | *.hex 42 | 43 | # Test data 44 | /test/data/ 45 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | 3 | # Install build tools 4 | RUN apt-get update \ 5 | && apt-get install -y build-essential git 6 | 7 | # Install OpenBLAS 8 | RUN apt-get update \ 9 | && apt-get install -y gfortran 10 | RUN git clone https://github.com/xianyi/OpenBLAS.git /tmp/OpenBLAS \ 11 | && cd /tmp/OpenBLAS \ 12 | && [ $(getconf _NPROCESSORS_ONLN) = 1 ] && export USE_OPENMP=0 || export USE_OPENMP=1 \ 13 | && make NO_AFFINITY=1 \ 14 | && make install \ 15 | && rm -rf /tmp/OpenBLAS 16 | 17 | # Install Torch 18 | RUN apt-get update \ 19 | && apt-get install -y cmake curl unzip libreadline-dev libjpeg-dev \ 20 | libpng-dev ncurses-dev imagemagick gnuplot gnuplot-x11 libssl-dev \ 21 | libzmq3-dev graphviz 22 | RUN git clone https://github.com/torch/distro.git ~/torch --recursive \ 23 | && cd ~/torch \ 24 | && ./install.sh 25 | 26 | # Export environment variables manually 27 | ENV LUA_PATH='/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;/root/torch/install/share/lua/5.1/?.lua;/root/torch/install/share/lua/5.1/?/init.lua;./?.lua;/root/torch/install/share/luajit-2.1.0-alpha/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua' \ 28 | LUA_CPATH='/root/.luarocks/lib/lua/5.1/?.so;/root/torch/install/lib/lua/5.1/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so' \ 29 | PATH=/root/torch/install/bin:$PATH \ 30 | LD_LIBRARY_PATH=/root/torch/install/lib:$LD_LIBRARY_PATH \ 31 | DYLD_LIBRARY_PATH=/root/torch/install/lib:$DYLD_LIBRARY_PATH 32 | 33 | # Install required dependencies for ffmpeg.lua 34 | RUN echo "deb http://ppa.launchpad.net/kirillshkrogalev/ffmpeg-next/ubuntu trusty main" \ 35 | > /etc/apt/sources.list.d/ffmpeg.list \ 36 | && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8EFE5982 37 | RUN apt-get update \ 38 | && apt-get install -y \ 39 | cpp \ 40 | libavformat-ffmpeg-dev \ 41 | libavcodec-ffmpeg-dev \ 42 | libavutil-ffmpeg-dev \ 43 | libavfilter-ffmpeg-dev 44 | 45 | # Clean up 46 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 47 | 48 | # Install busted for running tests 49 | RUN luarocks install busted 50 | 51 | # Make working directory for this project 52 | RUN mkdir -p /app/test 53 | WORKDIR /app 54 | 55 | # Download test data 56 | COPY ./test/download_test_data.sh /app/test/ 57 | RUN cd test && ./download_test_data.sh 58 | 59 | COPY ./test/* /app/test/ 60 | COPY ./src /app/src 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Aiden Nibali 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ffmpeg-ffi 2 | 3 | LuaJIT FFI bindings to FFmpeg libraries. 4 | 5 | ## Usage 6 | 7 | local ffmpeg = require('ffmpeg') 8 | 9 | local ascii_frame = ffmpeg.new('./example.mpg') 10 | :filter('gray', 'scale=40:12') 11 | :read_video_frame() 12 | :to_ascii() 13 | 14 | print(ascii_frame) 15 | 16 | ### Torch 17 | 18 | If you have Torch installed, load the enhanced version of the library. 19 | 20 | local ffmpeg = require('ffmpeg.torch') 21 | 22 | local byte_tensor = ffmpeg.new('./example.mpg') 23 | :filter('rgb24', 'scale=512:512') 24 | :read_video_frame() 25 | :to_byte_tensor() 26 | 27 | local float_tensor = first_frame_tensor:float():div(255) 28 | -------------------------------------------------------------------------------- /build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | docker-compose stop 4 | docker-compose rm -f 5 | docker-compose build 6 | docker-compose run --rm ffmpeg-lua busted test 7 | -------------------------------------------------------------------------------- /config.ld: -------------------------------------------------------------------------------- 1 | title = 'ffmpeg-ffi docs' 2 | project = 'ffmpeg-ffi' 3 | file = {'src/'} 4 | topics = {'README.md', 'LICENSE'} 5 | format = 'markdown' 6 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 |
6 |ffmpeg | 53 |Lua bindings to FFmpeg libraries. | 54 |
ffmpeg.torch | 57 |Torch utilities for Lua bindings to FFmpeg libraries. | 58 |
README.md | 64 |65 | |
LICENSE | 68 |69 | |
ffmpeg
Lua bindings to FFmpeg libraries.
58 |59 | 60 |
61 |new (path) | 73 |Opens a video file for reading. | 74 |
Video:filter (pixel_format_name[, filterchain='null']) | 80 |Sets a filter to apply to the video. | 81 |
Video:duration () | 84 |Gets the video duration in seconds. | 85 |
Video:pixel_format_name () | 88 |Gets the name of the video pixel format. | 89 |
Video:read_video_frame () | 92 |Reads the next video frame. | 93 |
VideoFrame:to_ascii () | 99 |Converts the video frame to an ASCII visualisation. | 100 |
184 | -- Set up a filter which scales the video to 128x128 pixels, flips it 185 | -- horizontally and sets the output pixel format to 24-bit RGB: 186 | video = video:filter('rgb24', 'scale=128x128,hflip')187 | 188 | 189 |
ffmpeg.torch
Torch utilities for Lua bindings to FFmpeg libraries.
56 |The Torch module must 57 | be installed for ffmpeg.torch to work.
58 |VideoFrame:to_byte_tensor () | 70 |Converts the video frame to a Torch tensor. | 71 |
monad
Monad stuffs.
54 |Some code is based on 55 | Douglas Crockford's JavaScript monads.
56 |monad.result
A theoretical union type for Value and Error.
60 | For example, if a function is documented as returning a string Result
,
61 | this means that it returns a Value wrapping a string on success, or an
62 | Error otherwise.
Here's an example of using a function that returns a Result
:
68 | some_function():and_then(function(value) 69 | print('some_function returned ' .. value) 70 | end):catch(function(error_message)) 71 | print('Error calling some_function: ' .. error_message) 72 | end) 73 |74 | 75 |
However, the real beauty of this approach comes with chaining calls:
76 | 77 | 78 |79 | create_a_shape() 80 | :scale(2) 81 | :rotate(45) 82 | :translate(10, 5) 83 | :catch(function(error_message)) 84 | print('Error creating and transforming shape: ' .. error_message) 85 | end) 86 |87 | 88 |
In the above example we assume that createashape() returns a Result
.
89 | If any of the steps along the way fails, no further methods will be called
90 | and the catch function will be triggered. If all of the steps are successful,
91 | the catch function will not be called.
At some point you may want to unwrap a Value to get the actual value inside 94 | of it. A good pattern for doing this is as follows:
95 | 96 | 97 |98 | local my_shape = create_a_shape() 99 | :scale(2) 100 | :rotate(45) 101 | :translate(10, 5) 102 | :catch(function(error_message)) 103 | return default_shape 104 | end) 105 | :get() 106 |107 | 108 |
:get
is a special function which returns the value wrapped by a Value.
109 | But be careful! If you call get on an Error then a Lua error will be
110 | raised - this is why in the example above we make sure that we make a
111 | default value available in the case of an Error.
Error () | 124 |Returns a factory for making Error monads. | 125 |
Value () | 128 |Returns a factory for making Value monads. | 129 |
m:done (...) | 135 |Alias for Error:get |
136 |
m:get () | 139 |Rethrows the error. | 140 |
m:catch (callback) | 143 |Calls function callback with the error message. |
144 |
m:and_then (callback) | 147 |Returns self (callback is not called). |
148 |
m:done (...) | 154 |Alias for Value:get |
155 |
m:get () | 158 |Returns the wrapped value. | 159 |
m:catch (callback) | 162 |Returns self (callback is not called). |
163 |
m:and_then (callback) | 166 |Calls function callback with the wrapped value. |
167 |
192 | local error_factory = monad.Error() 193 | local error_monad = error_factory('An error occurred!')194 | 195 | 196 |
212 | local value_factory = monad.Value() 213 | local value_monad = value_factory(42)214 | 215 | 216 |
A monad which represents an error result.
223 | 224 |An ErrorMonad will:
225 | 226 |:get
or :done
is called on it.callback
with the error message when :catch(callback)
229 | is called on it.Error:get
241 |
242 |
243 | callback
with the error message.
285 |
286 |
287 | callback
.
302 | callback
is not called).
314 |
315 |
316 | A monad which represents a successful result value.
343 | 344 |A Value monad will:
345 | 346 |:get
or :done
is called on it.callback
with the wrapped value when
349 | :and_then(callback)
is called on it.:catch()
.Result
.Value:get
364 |
365 |
366 | callback
is not called).
408 |
409 |
410 | callback
with the wrapped value.
437 |
438 |
439 | callback
.
454 | result
A theoretical union type for Value and Error.
60 | For example, if a function is documented as returning a string Result
,
61 | this means that it returns a Value wrapping a string on success, or an
62 | Error otherwise.
Here's an example of using a function that returns a Result
:
68 | some_function():and_then(function(value) 69 | print('some_function returned ' .. value) 70 | end):catch(function(error_message)) 71 | print('Error calling some_function: ' .. error_message) 72 | end) 73 |74 | 75 |
However, the real beauty of this approach comes with chaining calls:
76 | 77 | 78 |79 | create_a_shape() 80 | :scale(2) 81 | :rotate(45) 82 | :translate(10, 5) 83 | :catch(function(error_message)) 84 | print('Error creating and transforming shape: ' .. error_message) 85 | end) 86 |87 | 88 |
In the above example we assume that createashape() returns a Result
.
89 | If any of the steps along the way fails, no further methods will be called
90 | and the catch function will be triggered. If all of the steps are successful,
91 | the catch function will not be called.
At some point you may want to unwrap a Value to get the actual value inside 94 | of it. A good pattern for doing this is as follows:
95 | 96 | 97 |98 | local my_shape = create_a_shape() 99 | :scale(2) 100 | :rotate(45) 101 | :translate(10, 5) 102 | :catch(function(error_message)) 103 | return default_shape 104 | end) 105 | :get() 106 |107 | 108 |
:get
is a special function which returns the value wrapped by a Value.
109 | But be careful! If you call get on an Error then a Lua error will be
110 | raised - this is why in the example above we make sure that we make a
111 | default value available in the case of an Error.
Error () | 124 |Returns a factory for making Error monads. | 125 |
Value () | 128 |Returns a factory for making Value monads. | 129 |
monad:done (...) | 135 |Alias for Error:get |
136 |
monad:get () | 139 |Rethrows the error. | 140 |
monad:catch (callback) | 143 |Calls function callback with the error message. |
144 |
monad:and_then (callback) | 147 |Returns self (callback is not called). |
148 |
monad:done (...) | 154 |Alias for Value:get |
155 |
monad:get () | 158 |Returns the wrapped value. | 159 |
monad:catch (callback) | 162 |Returns self (callback is not called). |
163 |
monad:and_then (callback) | 166 |Calls function callback with the wrapped value. |
167 |
Returns a factory for making Error monads.
184 | 185 |local error_factory = monad.Error()
186 | local error_monad = error_factory('An error occurred!')
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 | Returns a factory for making Value monads.
204 | 205 |local value_factory = monad.Value()
206 | local value_monad = value_factory(42)
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | A monad which represents an error result.
223 | 224 |An Error monad will:
225 | 226 |:get
or :done
is called on it.callback
with the error message when :catch(callback)
229 | is called on it.Error:get
241 |
242 |
243 | callback
with the error message.
285 |
286 |
287 | callback
.
302 | callback
is not called).
314 |
315 |
316 | A monad which represents a successful result value.
343 | 344 |A Value monad will:
345 | 346 |:get
or :done
is called on it.callback
with the wrapped value when
349 | :and_then(callback)
is called on it.:catch()
.Result
.Value:get
364 |
365 |
366 | callback
is not called).
408 |
409 |
410 | callback
with the wrapped value.
437 |
438 |
439 | callback
.
454 | Copyright (c) 2015 Aiden Nibali
53 | 54 |Permission is hereby granted, free of charge, to any person obtaining a copy 55 | of this software and associated documentation files (the "Software"), to deal 56 | in the Software without restriction, including without limitation the rights 57 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58 | copies of the Software, and to permit persons to whom the Software is 59 | furnished to do so, subject to the following conditions:
60 | 61 |The above copyright notice and this permission notice shall be included in all 62 | copies or substantial portions of the Software.
63 | 64 |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 66 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 67 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 68 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 69 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 70 | SOFTWARE. 71 | 72 |
LuaJIT FFI bindings to FFmpeg libraries.
58 | 59 | 60 |64 | local ffmpeg = require('ffmpeg') 65 | 66 | ffmpeg.new('./example.mpg') 67 | :filter('gray', 'scale=40:12') 68 | :read_video_frame() 69 | :to_ascii() 70 | :and_then(function(ascii_frame) 71 | print(ascii_frame) 72 | end) 73 | :catch(function(err) 74 | print('An error occurred: ' .. err) 75 | end) 76 |77 | 78 |
If you have Torch installed, load the enhanced version of the library.
81 | 82 | 83 |84 | local ffmpeg = require('ffmpeg.torch') 85 | 86 | local first_frame_tensor = ffmpeg.new('./example.mpg') 87 | :filter('rgb24', 'scale=512:512') 88 | :read_video_frame() 89 | :to_byte_tensor() 90 | :catch(function(err) 91 | -- Use the Lena image in case of error 92 | return image:lena() 93 | end) 94 | :get() 95 |96 | 97 | 98 | 99 |